@sentientui/react 0.19.1 → 0.21.0

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/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/provider.tsx","../src/weights-store.ts","../src/preview-mode.ts","../src/override-events.ts","../src/devtools-config.ts","../src/adaptive-shared.ts","../src/devtools-registry.ts","../src/adaptive.tsx","../src/use-assignment.ts","../src/dev-override.ts","../src/adaptive-text.tsx","../src/use-adaptive-goal.ts","../src/persona-script.tsx","../src/use-adaptive-tokens.ts","../src/use-slot-result.ts","../src/use-adaptive.ts","../src/adaptive-group.tsx","../src/segment.ts","../src/agent-feed.ts"],"sourcesContent":["export { AdaptiveProvider, useSentient, useInitialAssignments, useLayoutOrder, useAdaptiveApiBaseUrl } from './provider.js';\nexport type { AdaptiveProviderProps, SsrFallback } from './provider.js';\n\nexport { Adaptive } from './adaptive.js';\nexport type {\n AdaptiveProps,\n GoalConfig,\n ClickGoal,\n ScrollDepthGoal,\n FormSubmitGoal,\n CompositeGoal,\n WeightedStep,\n WeightedCompositeGoal,\n MicroSignalGoals,\n MicroSignalGoalConfig,\n} from './adaptive.js';\n\nexport { AdaptiveText } from './adaptive-text.js';\nexport type { AdaptiveTextProps } from './adaptive-text.js';\n\n/**\n * @deprecated Use {@link useAdaptive} instead — it selects a variant AND wires\n * exposure, goal, and micro-signal tracking. `useAssignment` only selects, so a\n * component built on it directly records no learning signal. Kept exported for\n * back-compat (it is `useAdaptive`'s internal selection engine); moving to\n * internal-only in 1.0.0.\n */\nexport { useAssignment } from './use-assignment.js';\nexport type { AssignmentState } from './use-assignment.js';\n\nexport { useAdaptiveGoal } from './use-adaptive-goal.js';\nexport type { FireGoal } from './use-adaptive-goal.js';\n\nexport { SentientPersonaScript } from './persona-script.js';\nexport type { SentientPersonaScriptProps } from './persona-script.js';\n\nexport { useAdaptiveTokens } from './use-adaptive-tokens.js';\nexport type { UseAdaptiveTokensOptions, UseAdaptiveTokensResult } from './use-adaptive-tokens.js';\n\nexport { useAdaptive } from './use-adaptive.js';\nexport type { UseAdaptiveResult, UseAdaptiveBind } from './use-adaptive.js';\n\nexport { useAdaptivePersona } from './use-slot-result.js';\nexport type { AdaptivePersona } from './use-slot-result.js';\n\nexport { AdaptiveGroup } from './adaptive-group.js';\nexport type { AdaptiveGroupProps } from './adaptive-group.js';\n\nexport type { ComponentWeights, VariantWeight } from './weights-store.js';\n\nexport { detectSegment } from './segment.js';\n\nexport {\n defineAgentContent,\n getAgentContent,\n buildAgentFeed,\n renderAgentJsonLd,\n renderAgentJsonLdBody,\n renderAgentMarkdown,\n} from './agent-feed.js';\nexport type { AgentFeed, AgentBlock } from './agent-feed.js';\n\n// Re-exported from core so a React app can wire its consent banner to the SDK\n// without adding @sentientui/core as a direct dependency — the docs already\n// point React users at grantConsent(), so it belongs on this entry.\n//\n// Safe here, unlike the server-only helpers re-exported from /next: this index\n// carries no 'use client' directive, and grantConsent is browser-only (it\n// returns immediately during SSR), so it is only ever called from a client\n// component and never becomes a client reference invoked on the server.\nexport { grantConsent } from '@sentientui/core';\n","'use client';\n\ndeclare const process: { env?: { NODE_ENV?: string } } | undefined;\n\nimport {\n createContext,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState,\n useSyncExternalStore,\n type ReactNode,\n} from 'react';\nimport {\n detectDeviceClass,\n detectTrafficSource,\n init,\n type SentientClient,\n type SentientConfig,\n type SlotResult,\n} from '@sentientui/core';\nimport { update as updateWeightsStore, type ComponentWeights } from './weights-store.js';\nimport { getPreviewMode, subscribePreview, createPreviewClient } from './preview-mode.js';\nimport { subscribeOverridesChanged } from './override-events.js';\nimport { publishDevtoolsConfig } from './devtools-config.js';\nimport { registerSections } from './devtools-registry.js';\n\n/**\n * Mirrors the segment derivation inside core `init()` so the cache key used\n * by `useAssignment` always matches the key `assign()` writes under. Before\n * this, the context defaulted to 'desktop:direct' while core used the\n * detected segment — a systematic cache miss for every integration that\n * didn't pass `sessionSegment` explicitly.\n */\nfunction deriveDefaultSegment(): string {\n if (typeof window === 'undefined') return 'desktop:direct';\n try {\n const device = detectDeviceClass(navigator.userAgent ?? '');\n const source = detectTrafficSource(document.referrer ?? '', window.location.origin);\n return `${device}:${source}`;\n } catch {\n return 'desktop:direct';\n }\n}\n\nconst DEFAULT_API_BASE_URL = 'https://api.sentient-ui.com/v1';\n\n/** How to render adaptive slots during SSR when assignments are not preloaded. */\nexport type SsrFallback = 'first' | 'none';\n\ntype AdaptiveContextValue = {\n client: SentientClient | null;\n // The publishable API key (pk_…). Historically named `projectId` because the\n // API uses it as the project identifier on the wire, but it is the API key,\n // not the project UUID. Field renamed for clarity.\n apiKey: string;\n initialAssignments: Record<string, string>;\n sessionSegment: string;\n ssrFallback: SsrFallback;\n onAssignment: ((componentId: string, variantId: string) => void) | undefined;\n initialLayoutOrder: string[] | null;\n initialSlots: Record<string, SlotResult>;\n initialPersona: { persona: string; confidence: number } | null;\n apiBaseUrl: string;\n debug: boolean;\n};\n\nconst AdaptiveContext = createContext<AdaptiveContextValue>({\n client: null,\n apiKey: '',\n initialAssignments: {},\n sessionSegment: 'desktop:direct',\n ssrFallback: 'first',\n onAssignment: undefined,\n initialLayoutOrder: null,\n initialSlots: {},\n initialPersona: null,\n apiBaseUrl: DEFAULT_API_BASE_URL,\n debug: false,\n});\n\nexport type AdaptiveProviderProps = {\n apiKey: string;\n context: SentientConfig['context'];\n debug?: boolean;\n /**\n * SSR-preloaded assignments from `preloadAssignments()` / `loadAdaptiveAssignments()`.\n * Passed through to `useAssignment` as synchronous initial state so crawlers and\n * the first paint see real content (recommended for SEO).\n */\n initialAssignments?: Record<string, string>;\n /**\n * Bandit segment from SSR (`device:source`). Keeps cache, assign, and worker\n * weights on one row — must match `loadAdaptiveAssignments` / session upsert.\n */\n sessionSegment?: string;\n /**\n * When no `initialAssignments` exist for a component, `'first'` renders\n * `variantIds[0]` in server HTML (safe default for SEO). Use `'none'` only for\n * decorative slots marked `clientOnly`.\n * @default 'first'\n */\n ssrFallback?: SsrFallback;\n /**\n * Consent gate. When `false` the SDK is not initialised and no events are\n * sent. Flip to `true` (e.g. after the user accepts the cookie banner) to\n * initialise and begin tracking.\n */\n consent?: boolean;\n /**\n * Where to read the visitor's consent decision from, so the SDK can gate and\n * un-gate itself instead of the host app wiring `grantConsent()` by hand.\n *\n * Keep your own banner or CMP — this only tells us how to observe it. The\n * provider reads the source on mount, re-reads it whenever `event` fires, and\n * initialises the moment it grants. Nothing is requested and no cookie is set\n * until then, and there is no page reload.\n *\n * Because the provider owns the whole lifecycle there is no ordering rule to\n * get right: pass this instead of managing `consent` yourself.\n *\n * @example // cookie written by your own banner\n * consentFrom={{ cookie: 'cookie_consent', value: 'accepted', event: 'consent-decided' }}\n * @example // a CMP that exposes an object rather than a cookie\n * consentFrom={{ check: () => window.Cookiebot?.consent?.statistics === true,\n * event: 'CookiebotOnAccept' }}\n */\n consentFrom?: {\n /** Cookie to read. Granted when its value equals `value`. */\n cookie?: string;\n /** Cookie value that means granted. @default 'accepted' */\n value?: string;\n /** Predicate for CMPs with a JS API. Takes precedence over `cookie`. */\n check?: () => boolean;\n /**\n * `window` event that signals a decision. The source is re-read when it\n * fires — the event's payload is never trusted — so any CMP's event works.\n */\n event?: string;\n };\n /**\n * Behavior before consent is granted. Pass `'statistical_winner'` to serve the\n * best-performing variant via `GET /v1/winner` with zero tracking while the\n * consent banner is showing. Requires `consent: false`.\n * @see SentientConfig.preConsentBehavior\n */\n preConsentBehavior?: 'statistical_winner' | 'control';\n /**\n * Honor the browser's Do Not Track signal. Defaults to `true`: when DNT is\n * enabled the SDK sets no cookies and sends no tracking data (overriding\n * `consent: true`). Set `false` to make your own consent gate authoritative.\n * @see SentientConfig.respectDoNotTrack\n */\n respectDoNotTrack?: boolean;\n /**\n * Called once per component the first time a variant is resolved for that\n * component in this session. Use to forward assignments to your own analytics\n * (Mixpanel, PostHog, Segment, etc.) without having to wrap `useAssignment`.\n */\n onAssignment?: (componentId: string, variantId: string) => void;\n /**\n * SSR-preloaded section order from `loadAdaptiveDecision()`.\n * Pass the `layoutOrder` field from `DecideResult`. When set,\n * `useLayoutOrder()` returns this on first render so there is no layout shift.\n */\n initialLayoutOrder?: string[] | null;\n /**\n * SSR-preloaded slot results from `loadAdaptiveDecision()` (the `slots`\n * field of its result). Guarantees `useAdaptiveTokens`/`AdaptiveGroup`\n * render the decided arm in server HTML — zero flicker, hydration-safe.\n */\n initialSlots?: Record<string, SlotResult>;\n /**\n * Persona decided during SSR (`persona` + `confidence` fields of\n * `loadAdaptiveDecision()`'s result). Adopted by the core client;\n * rendered into html attributes only by `SentientPersonaScript`.\n */\n initialPersona?: { persona: string; confidence: number };\n /**\n * Base URL of the Sentient API (no trailing slash). Read by the devtools\n * panel for /v1/explain and by future client helpers. Defaults to the\n * hosted API.\n */\n apiBaseUrl?: string;\n /**\n * Session ID generated during SSR (the `sessionId` field returned by\n * `loadAdaptiveAssignments` / `loadAdaptiveDecision`). When provided and no\n * existing session cookie or localStorage entry is found, the client adopts\n * this ID so events and goals are attributed to the same session the server\n * used for variant assignment.\n */\n ssrSessionId?: string;\n /**\n * ISO 3166-1 alpha-2 country code. Pass the value of the `CF-IPCountry`\n * header from your Next.js server component to populate country on landing\n * sessions without client-side geo lookup.\n */\n country?: string;\n /**\n * Keyless local mode. 'auto' (default) simulates decisions on-device in\n * development builds when no valid API key is configured; `true` forces the\n * local engine; `false` restores the silent keyless no-op.\n * @see SentientConfig.localMode\n */\n localMode?: 'auto' | boolean;\n /**\n * DOM graph scanning + page-structure sync. ON by default: the provider\n * dynamically loads `@sentientui/core/graph` and uses its graph-capable\n * `init()` for the single client, so the SDK scans your page structure,\n * auto-detects semantic sections, and syncs them to power personas and the\n * dashboard graph page. Pass `false` to keep the lean bundle only.\n */\n enableGraph?: boolean;\n /**\n * Include captured heading / DOM text in graph sync payloads. OFF by default.\n * Only applies when graph scanning is enabled (`enableGraph` not `false`).\n */\n captureDomText?: boolean;\n /**\n * Behavioral engagement capture (per-section dwell/scroll + semantic section\n * registration) powering personas. ON by default — pass `false` to disable.\n * Never runs for a DNT/GPC or consent-gated visitor (no client → no capture).\n */\n engagement?: boolean;\n children: ReactNode;\n};\n\n/**\n * Watches a {@link AdaptiveProviderProps.consentFrom} source and reports whether\n * it currently grants consent. Returns false (and subscribes to nothing) when no\n * source is configured.\n */\nfunction useConsentSource(source: AdaptiveProviderProps['consentFrom']): boolean {\n const [granted, setGranted] = useState(false);\n\n // The source is usually an inline object literal, so its identity changes\n // every render. Read it through a ref and key the effect on its primitives,\n // otherwise the listener would be torn down and re-added on every render.\n const sourceRef = useRef(source);\n sourceRef.current = source;\n\n const { cookie, value, event } = source ?? {};\n const hasCheck = typeof source?.check === 'function';\n\n useEffect(() => {\n const read = (): boolean => {\n const s = sourceRef.current;\n if (!s) return false;\n if (s.check) return s.check() === true;\n if (!s.cookie || typeof document === 'undefined') return false;\n const want = `${s.cookie}=${s.value ?? 'accepted'}`;\n return document.cookie.split('; ').some((c) => c.trim() === want);\n };\n\n if (read()) {\n setGranted(true);\n return;\n }\n if (!event) return;\n\n // Re-read rather than trusting the event payload, so this works with any\n // CMP's event shape (CookiebotOnAccept, OneTrustGroupsUpdated, …) and a\n // \"declined\" decision correctly leaves us gated.\n const onDecision = (): void => {\n if (read()) setGranted(true);\n };\n window.addEventListener(event, onDecision);\n return () => window.removeEventListener(event, onDecision);\n }, [cookie, value, event, hasCheck]);\n\n return granted;\n}\n\n/**\n * Initialises the Sentient core SDK in a useEffect (SSR-safe) and exposes the\n * client via React context. Re-initialises when consent changes.\n */\nexport function AdaptiveProvider(props: AdaptiveProviderProps): JSX.Element {\n const [client, setClient] = useState<SentientClient | null>(null);\n // Derived once per mount: identical to what core init() computes, so cache\n // reads (context segment) and cache writes (core segment) always agree.\n const [sessionSegment] = useState(() => props.sessionSegment ?? deriveDefaultSegment());\n // Devtools preview: when on, expose an event-suppressing client so previewing\n // variants/personas writes nothing. Off by default (inert in production).\n const [previewOn, setPreviewOn] = useState(getPreviewMode());\n useEffect(() => subscribePreview(() => setPreviewOn(getPreviewMode())), []);\n\n // When a consentFrom source is configured it owns the gate: start closed and\n // open only once the source grants. An explicit consent={true} (e.g. resolved\n // from the cookie on the server by AdaptiveRoot) short-circuits it, so a\n // returning visitor isn't gated waiting for a client-side re-read.\n const sourceGranted = useConsentSource(props.consentFrom);\n const consent = props.consentFrom ? props.consent === true || sourceGranted : props.consent;\n\n useEffect(() => {\n // When consent is explicitly false with no preConsentBehavior, tear down any existing client.\n if (consent === false && !props.preConsentBehavior) {\n setClient((prev: SentientClient | null) => {\n prev?.destroy();\n return null;\n });\n return;\n }\n\n const config = {\n apiKey: props.apiKey,\n context: props.context,\n debug: props.debug,\n initialAssignments: props.initialAssignments,\n sessionSegment,\n consent,\n preConsentBehavior: props.preConsentBehavior,\n respectDoNotTrack: props.respectDoNotTrack,\n ssrSessionId: props.ssrSessionId,\n country: props.country,\n localMode: props.localMode,\n initialSlots: props.initialSlots,\n initialPersona: props.initialPersona,\n ingestUrl: props.apiBaseUrl ? `${props.apiBaseUrl.replace(/\\/$/, '')}/events` : undefined,\n };\n\n // Track the client created by this effect run so cleanup destroys exactly\n // the right one, and so a late-resolving dynamic import can bail if the\n // effect was already torn down (unmount / consent change).\n let cancelled = false;\n let created: SentientClient | null = null;\n let stopEngagement: (() => void) | null = null;\n\n // Engagement capture (default ON): per-section dwell/scroll + semantic\n // section registration, lazy-loaded so the lean bundle stays lean. Only\n // ever started for an initialised client, so consent/DNT gates are\n // inherited (and the capture module re-checks DNT internally).\n const startEngagement = (c: SentientClient): void => {\n if (props.engagement === false) return;\n void import('@sentientui/core/engagement').then(({ startEngagementCapture }) => {\n if (cancelled) return;\n stopEngagement = startEngagementCapture(c, {\n apiKey: props.apiKey,\n apiBase: props.apiBaseUrl ? props.apiBaseUrl.replace(/\\/$/, '') : undefined,\n });\n });\n };\n\n if (props.enableGraph !== false) {\n // Graph scanning is the default — load the graph entry dynamically so the\n // scanner never lands in the lean bundle. The provider still creates ONE\n // client (graph-capable). Pass enableGraph={false} for the lean client.\n void import('@sentientui/core/graph').then(({ init: initGraph }) => {\n if (cancelled) return;\n created = initGraph({ ...config, graph: true, captureDomText: props.captureDomText === true });\n setClient(created);\n startEngagement(created);\n });\n } else {\n created = init(config);\n setClient(created);\n startEngagement(created);\n }\n\n return () => {\n cancelled = true;\n stopEngagement?.();\n // dispose, not destroy: effect cleanup runs on unmount, StrictMode's\n // dev double-invoke, and consent re-init — the visitor identity must\n // survive all of those. Full destroy() happens only on the explicit\n // consent-revocation branch above.\n created?.dispose();\n };\n // Re-init when consent changes — whether that came from the prop or from a\n // consentFrom source granting. Other props (incl. enableGraph) are\n // intentionally stable for a session.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [consent]);\n\n // Poll /v1/weights every 60 s so long-lived sessions see updated bandit weights\n // without a page reload. useAssignment subscribers react via weights-store.\n useEffect(() => {\n if (!client) return;\n let cancelled = false;\n const poll = async (): Promise<void> => {\n if (cancelled) return;\n let entries;\n try {\n entries = await client.fetchWeights();\n } catch {\n // Network/transient error: skip this cycle and retry on the next\n // interval. Swallowed deliberately so a failed poll never surfaces as\n // an unhandled rejection.\n return;\n }\n if (cancelled) return;\n for (const entry of entries) {\n const weights: ComponentWeights = {\n componentId: entry.componentId,\n updatedAt: entry.updatedAt,\n variants: entry.variants.map((v) => ({\n variantId: v.variantId,\n pulls: v.pulls,\n avgReward: v.avgReward ?? 0,\n })),\n };\n updateWeightsStore(entry.componentId, weights);\n }\n };\n void poll();\n const timerId = setInterval(() => void poll(), 60_000);\n return () => {\n cancelled = true;\n clearInterval(timerId);\n };\n }, [client]);\n\n const ssrFallback = props.ssrFallback ?? 'first';\n // Strip a trailing slash so consumers (devtools /explain, useAdaptiveApiBaseUrl)\n // build URLs the same way the core client does (it strips before appending\n // /events and /section-map) — otherwise an apiBaseUrl ending in \"/\" yields a\n // double slash like \".../v1//explain\".\n const apiBaseUrl = (props.apiBaseUrl ?? DEFAULT_API_BASE_URL).replace(/\\/$/, '');\n\n // The init effect above re-runs only on `props.consent`: apiKey / context /\n // country / apiBaseUrl are captured once and are deliberately stable for the\n // session, so changing them at runtime silently no-ops. That silence is\n // surprising — warn (dev only) when one actually changes value after init, so\n // the no-op is visible. To apply a new value, remount the provider (e.g. a\n // changing React `key`).\n const frozenConfigRef = useRef<{\n apiKey: string;\n context: SentientConfig['context'];\n country: string | undefined;\n apiBaseUrl: string;\n } | null>(null);\n useEffect(() => {\n if (typeof process !== 'undefined' && process.env?.NODE_ENV === 'production') return;\n const current = { apiKey: props.apiKey, context: props.context, country: props.country, apiBaseUrl };\n const prev = frozenConfigRef.current;\n frozenConfigRef.current = current;\n if (prev === null) return; // first run: capture the frozen baseline, nothing to compare\n for (const key of ['apiKey', 'context', 'country', 'apiBaseUrl'] as const) {\n if (!Object.is(prev[key], current[key])) {\n console.warn(\n `[sentient] AdaptiveProvider: \\`${key}\\` changed after initialisation, but the SDK client is stable for the session and only re-inits on \\`consent\\` — the new value is ignored. Remount the provider (e.g. via a changing \\`key\\` prop) to apply it.`,\n );\n }\n }\n }, [props.apiKey, props.context, props.country, apiBaseUrl]);\n\n // Publish devtools config through window: the /devtools entry is a separate\n // bundle and cannot read this provider's context instance. Dev-only.\n useEffect(() => {\n if (typeof process !== 'undefined' && process.env?.NODE_ENV === 'production') return;\n publishDevtoolsConfig({\n apiKey: props.apiKey,\n apiBaseUrl,\n isLocal: client?.isLocal === true,\n });\n }, [client, props.apiKey, apiBaseUrl]);\n\n // Sections registry for devtools /v1/explain + local simulation.\n useEffect(() => {\n if (props.initialLayoutOrder && props.initialLayoutOrder.length > 0) {\n registerSections(props.initialLayoutOrder);\n }\n }, [props.initialLayoutOrder]);\n\n // The client exposed to consumers — wrapped to suppress events while previewing.\n const exposedClient = useMemo(\n () => (client && previewOn ? createPreviewClient(client) : client),\n [client, previewOn],\n );\n\n // Memoized so unrelated parent re-renders don't cascade through every\n // useSentient / useAssignment consumer via a fresh context object.\n const value = useMemo<AdaptiveContextValue>(\n () => ({\n client: exposedClient,\n apiKey: props.apiKey,\n initialAssignments: props.initialAssignments ?? {},\n sessionSegment,\n ssrFallback,\n onAssignment: props.onAssignment,\n initialLayoutOrder: props.initialLayoutOrder ?? null,\n initialSlots: props.initialSlots ?? {},\n initialPersona: props.initialPersona ?? null,\n apiBaseUrl,\n debug: props.debug ?? false,\n }),\n [\n exposedClient,\n props.apiKey,\n props.initialAssignments,\n sessionSegment,\n ssrFallback,\n props.onAssignment,\n props.initialLayoutOrder,\n props.initialSlots,\n props.initialPersona,\n apiBaseUrl,\n props.debug,\n ],\n );\n\n return (\n <AdaptiveContext.Provider value={value}>\n {props.children}\n </AdaptiveContext.Provider>\n );\n}\n\n/**\n * Returns the SentientClient, or null until the provider has finished\n * initialising on the client.\n */\nexport function useSentient(): SentientClient | null {\n return useContext(AdaptiveContext).client;\n}\n\n/** Internal: publishable API key carried alongside the client. */\nexport function useAdaptiveApiKey(): string {\n return useContext(AdaptiveContext).apiKey;\n}\n\n/** Internal: SSR-preloaded assignments for hydration-safe first render. */\nexport function useInitialAssignments(): Record<string, string> {\n return useContext(AdaptiveContext).initialAssignments;\n}\n\n/** Internal: bandit segment aligned with SSR session upsert. */\nexport function useSessionSegment(): string {\n return useContext(AdaptiveContext).sessionSegment;\n}\n\n/** Internal: SSR fallback strategy when a slot has no preloaded assignment. */\nexport function useSsrFallback(): SsrFallback {\n return useContext(AdaptiveContext).ssrFallback;\n}\n\n/** Internal: forwarding hook for consumer analytics integration. */\nexport function useOnAssignment(): ((componentId: string, variantId: string) => void) | undefined {\n return useContext(AdaptiveContext).onAssignment;\n}\n\n/** Internal: debug flag from the provider config, for dev-only diagnostic logging. */\nexport function useDebug(): boolean {\n return useContext(AdaptiveContext).debug;\n}\n\n/**\n * Returns the persona-specific section order from SSR, or null when no\n * sections were declared on AdaptiveRoot or reliability is below threshold.\n * Devtools/testing can force it via `window.__sentient_layout_override`;\n * consumers re-render when the devtools notifies an override change.\n */\nexport function useLayoutOrder(): string[] | null {\n const contextOrder = useContext(AdaptiveContext).initialLayoutOrder;\n const override = useSyncExternalStore(\n subscribeOverridesChanged,\n () =>\n typeof window === 'undefined'\n ? null\n : ((window as unknown as { __sentient_layout_override?: string[] })\n .__sentient_layout_override ?? null),\n () => null,\n );\n return override ?? contextOrder;\n}\n\n/** Internal: SSR-preloaded slot results for hydration-safe first render. */\nexport function useInitialSlots(): Record<string, SlotResult> {\n return useContext(AdaptiveContext).initialSlots;\n}\n\n/** Internal: SSR-decided persona carried alongside the client. */\nexport function useInitialPersona(): { persona: string; confidence: number } | null {\n return useContext(AdaptiveContext).initialPersona;\n}\n\n/** Internal: configured API base URL (devtools fetches /v1/explain against this, never a relative URL). */\nexport function useAdaptiveApiBaseUrl(): string {\n return useContext(AdaptiveContext).apiBaseUrl;\n}\n","/** Per-component weights store with isolated subscriptions. */\n\nexport type VariantWeight = {\n variantId: string;\n pulls: number;\n avgReward: number;\n};\n\nexport type ComponentWeights = {\n componentId: string;\n variants: VariantWeight[];\n updatedAt: number;\n};\n\ntype Listener = (weights: ComponentWeights) => void;\n\nconst store = new Map<string, ComponentWeights>();\nconst listeners = new Map<string, Set<Listener>>();\n\n/**\n * Subscribes a listener to a single component. Returns an unsubscribe function.\n * Updates to other components never trigger this listener.\n */\nexport function subscribe(componentId: string, cb: Listener): () => void {\n let set = listeners.get(componentId);\n if (!set) {\n set = new Set();\n listeners.set(componentId, set);\n }\n set.add(cb);\n return () => {\n set!.delete(cb);\n if (set!.size === 0) listeners.delete(componentId);\n };\n}\n\n/**\n * Replaces the weights for a component and notifies only that component's\n * subscribers.\n */\nexport function update(componentId: string, weights: ComponentWeights): void {\n store.set(componentId, weights);\n const set = listeners.get(componentId);\n if (!set) return;\n for (const cb of set) {\n try {\n cb(weights);\n } catch {\n /* never throw to other listeners */\n }\n }\n}\n\n/**\n * Returns the latest known weights for a component, or null if none seen.\n */\nexport function getWeights(componentId: string): ComponentWeights | null {\n return store.get(componentId) ?? null;\n}\n\n/** Test-only: wipe the entire store. */\nexport function _resetWeightsStore(): void {\n store.clear();\n listeners.clear();\n}\n","import type { SentientClient } from '@sentientui/core';\n\ntype PreviewState = { on: boolean; listeners: Set<() => void> };\nconst ssrFallback: PreviewState = { on: false, listeners: new Set() };\n\n// Window-backed: the /devtools entry (a separate bundle) toggles preview mode\n// and the provider (main bundle) must observe it.\nfunction state(): PreviewState {\n if (typeof window === 'undefined') return ssrFallback;\n const w = window as unknown as { __sentient_preview?: PreviewState };\n if (!w.__sentient_preview) w.__sentient_preview = { on: false, listeners: new Set() };\n return w.__sentient_preview;\n}\n\nexport function setPreviewMode(on: boolean): void {\n const s = state();\n if (s.on === on) return;\n s.on = on;\n for (const fn of s.listeners) fn();\n}\n\nexport function getPreviewMode(): boolean {\n return state().on;\n}\n\nexport function subscribePreview(fn: () => void): () => void {\n const listeners = state().listeners;\n listeners.add(fn);\n return () => {\n listeners.delete(fn);\n };\n}\n\n/**\n * Wraps a client so it writes nothing: reads pass through, all emitters no-op.\n * Used while previewing variants/personas so no `variant_assigned`, goal, or\n * session events are sent.\n */\nexport function createPreviewClient(inner: SentientClient): SentientClient {\n return {\n isLocal: inner.isLocal,\n track: () => undefined,\n goal: () => undefined,\n componentGoal: () => undefined,\n identify: () => undefined,\n fetchWeights: () => Promise.resolve([]),\n getAssignment: (componentId, segment) => inner.getAssignment(componentId, segment),\n assign: (componentId, variantIds, agentData, agentDataByVariant) =>\n inner.assign(componentId, variantIds, agentData, agentDataByVariant),\n // Reads pass through; decide is a write (slot decisions persist server-side)\n // so preview mode never issues it.\n decide: () => Promise.resolve(null),\n getSlotResult: (slotId) => inner.getSlotResult(slotId),\n getPersona: () => inner.getPersona(),\n getGraph: () => inner.getGraph(),\n dispose: () => inner.dispose(),\n destroy: () => inner.destroy(),\n };\n}\n","/**\n * Cross-bundle re-render bus for devtools overrides. The main entry and the\n * /devtools entry are separate bundles, so state and notifications go through\n * window (a version counter + a DOM event) — never module-local state.\n */\nconst EVENT = 'sentient:overrides-changed';\n\ntype VersionWindow = Window & { __sentient_overrides_version?: number };\n\nexport function getOverridesVersion(): number {\n if (typeof window === 'undefined') return 0;\n return (window as VersionWindow).__sentient_overrides_version ?? 0;\n}\n\nexport function notifyOverridesChanged(): void {\n if (typeof window === 'undefined') return;\n const w = window as VersionWindow;\n w.__sentient_overrides_version = (w.__sentient_overrides_version ?? 0) + 1;\n window.dispatchEvent(new Event(EVENT));\n}\n\nexport function subscribeOverridesChanged(fn: () => void): () => void {\n if (typeof window === 'undefined') return () => undefined;\n window.addEventListener(EVENT, fn);\n return () => window.removeEventListener(EVENT, fn);\n}\n","/** Provider → devtools config handoff. Window-backed: the /devtools entry is a\n * separate bundle and cannot share the provider's React context instance. */\nexport type DevtoolsConfig = {\n apiKey: string;\n apiBaseUrl: string;\n isLocal: boolean;\n};\n\ntype ConfigWindow = Window & { __sentient_devtools_config?: DevtoolsConfig };\n\nexport function publishDevtoolsConfig(config: DevtoolsConfig): void {\n if (typeof window === 'undefined') return;\n (window as ConfigWindow).__sentient_devtools_config = config;\n}\n\nexport function readDevtoolsConfig(): DevtoolsConfig | null {\n if (typeof window === 'undefined') return null;\n return (window as ConfigWindow).__sentient_devtools_config ?? null;\n}\n","import type { SentientClient } from '@sentientui/core';\n\ndeclare const process: { env?: { NODE_ENV?: string } } | undefined;\n\n/**\n * True unless NODE_ENV is 'production'. Never `process?.env` — optional\n * chaining still throws ReferenceError on an undeclared global, and browsers\n * without a bundler shim (raw esbuild, vanilla script tags) have no `process`.\n */\nexport function isDevBuild(): boolean {\n return typeof process === 'undefined' || process.env?.NODE_ENV !== 'production';\n}\n\nexport type ScrollDepthGoal = { type: 'scroll_depth'; threshold: number };\nexport type ClickGoal = { type: 'click'; selector?: string };\nexport type FormSubmitGoal = { type: 'form_submit' };\nexport type CompositeGoal = { type: 'composite'; all: GoalConfig[] };\nexport type WeightedStep = { goal: GoalConfig; name: string; weight: number };\nexport type WeightedCompositeGoal = { type: 'weighted_composite'; steps: WeightedStep[] };\nexport type GoalConfig = ScrollDepthGoal | ClickGoal | FormSubmitGoal | CompositeGoal | WeightedCompositeGoal;\n\nexport function normalizeGoal(goal: string | GoalConfig): GoalConfig {\n if (typeof goal === 'string') return { type: 'click' };\n return goal;\n}\n\n/** The goalType label events are recorded under (named goal or config type). */\nexport function goalLabelOf(goal: string | GoalConfig): string {\n return typeof goal === 'string' ? goal : goal.type;\n}\n\nfunction isClickableTarget(el: EventTarget | null): boolean {\n if (!(el instanceof Element)) return false;\n const tag = el.tagName.toLowerCase();\n if (tag === 'a' || tag === 'button') return true;\n const role = el.getAttribute('role');\n return role === 'button';\n}\n\nfunction findClickable(start: Element, container: Element, selector?: string): boolean {\n if (selector) {\n try {\n let cursor: Element | null = start;\n while (cursor && cursor !== container) {\n if (cursor.matches(selector)) return true;\n cursor = cursor.parentElement;\n }\n } catch {\n // Invalid CSS selector — treat as no match rather than breaking all click handlers.\n }\n return false;\n }\n let cursor: Element | null = start;\n while (cursor && cursor !== container) {\n if (isClickableTarget(cursor)) return true;\n cursor = cursor.parentElement;\n }\n return false;\n}\n\nexport type GoalHandlers = {\n /** Primary goal completion. Latch-once semantics are the CALLER's job. */\n fireGoal: () => void;\n /** Weighted-composite step completion (already deduped per step here). */\n fireStep: (name: string, weight: number, stepIndex: number) => void;\n};\n\n/**\n * Attaches the goal-detection listeners `<Adaptive>`'s container uses —\n * click / form_submit / scroll_depth, composite (all-of), and\n * weighted_composite (independent steps). Returns the cleanup function.\n * Extracted from adaptive.tsx so useAdaptive / useAdaptiveTokens /\n * AdaptiveGroup wire the SAME machinery instead of duplicating it.\n */\nexport function attachGoalListeners(node: Element, goal: GoalConfig, handlers: GoalHandlers): () => void {\n // --- Weighted composite: each step fires independently as it completes ---\n if (goal.type === 'weighted_composite') {\n const firedSteps = new Set<number>();\n const wcCleanups: Array<() => void> = [];\n\n goal.steps.forEach(({ goal: sub, name: stepName, weight: stepWeight }, idx) => {\n const fireStep = (): void => {\n if (firedSteps.has(idx)) return;\n firedSteps.add(idx);\n handlers.fireStep(stepName, stepWeight, idx);\n };\n\n if (sub.type === 'click') {\n const onClick = (e: Event): void => {\n const target = e.target;\n if (!(target instanceof Element)) return;\n if (!findClickable(target, node, sub.selector)) return;\n fireStep();\n };\n node.addEventListener('click', onClick);\n wcCleanups.push(() => node.removeEventListener('click', onClick));\n return;\n }\n\n if (sub.type === 'form_submit') {\n const onSubmit = (e: Event): void => {\n if (!(e.target instanceof HTMLFormElement)) return;\n if (!node.contains(e.target)) return;\n fireStep();\n };\n node.addEventListener('submit', onSubmit);\n wcCleanups.push(() => node.removeEventListener('submit', onSubmit));\n return;\n }\n\n if (sub.type === 'scroll_depth') {\n const threshold = Math.max(0, Math.min(1, sub.threshold));\n const io = new IntersectionObserver(\n (entries) => {\n for (const entry of entries) {\n if (entry.intersectionRatio >= threshold) {\n fireStep();\n io.disconnect();\n break;\n }\n }\n },\n { threshold: [threshold] },\n );\n io.observe(node);\n wcCleanups.push(() => io.disconnect());\n }\n });\n\n return () => {\n for (const c of wcCleanups) c();\n };\n }\n // --- End weighted composite ---\n\n const subgoals: GoalConfig[] = goal.type === 'composite' ? goal.all : [goal];\n const remaining = new Set<number>(subgoals.map((_, i) => i));\n const checkComposite = (idx: number): void => {\n remaining.delete(idx);\n if (remaining.size === 0) handlers.fireGoal();\n };\n\n const cleanups: Array<() => void> = [];\n\n subgoals.forEach((sub, idx) => {\n if (sub.type === 'click') {\n const onClick = (e: Event): void => {\n const target = e.target;\n if (!(target instanceof Element)) return;\n if (!findClickable(target, node, sub.selector)) return;\n if (goal.type === 'composite') checkComposite(idx);\n else handlers.fireGoal();\n };\n node.addEventListener('click', onClick);\n cleanups.push(() => node.removeEventListener('click', onClick));\n return;\n }\n\n if (sub.type === 'form_submit') {\n const onSubmit = (e: Event): void => {\n if (!(e.target instanceof HTMLFormElement)) return;\n if (!node.contains(e.target)) return;\n if (goal.type === 'composite') checkComposite(idx);\n else handlers.fireGoal();\n };\n node.addEventListener('submit', onSubmit);\n cleanups.push(() => node.removeEventListener('submit', onSubmit));\n return;\n }\n\n if (sub.type === 'scroll_depth') {\n const threshold = Math.max(0, Math.min(1, sub.threshold));\n const io = new IntersectionObserver(\n (entries) => {\n for (const entry of entries) {\n if (entry.intersectionRatio >= threshold) {\n if (goal.type === 'composite') checkComposite(idx);\n else handlers.fireGoal();\n io.disconnect();\n break;\n }\n }\n },\n { threshold: [threshold] },\n );\n io.observe(node);\n cleanups.push(() => io.disconnect());\n return;\n }\n });\n\n return () => {\n for (const c of cleanups) c();\n };\n}\n\n/**\n * Records the `variant_assigned` exposure event.\n */\nexport function trackExposure(\n client: SentientClient,\n apiKey: string,\n componentId: string,\n variantId: string,\n): void {\n client.track({\n projectId: apiKey,\n componentId,\n variantId,\n eventType: 'variant_assigned',\n payload: {},\n });\n}\n","import { isDevBuild } from './adaptive-shared.js';\n\nexport type RegisteredComponent = { id: string; variantIds: string[]; goal?: string };\nexport type RegisteredSlot = {\n id: string;\n arms?: string[];\n dims?: Record<string, readonly string[]>;\n};\n\ntype RegistryState = {\n components: Map<string, RegisteredComponent>;\n slots: Map<string, RegisteredSlot>;\n sections: string[];\n listeners: Set<() => void>;\n /** Bumped on every mutation so `useSyncExternalStore` can read a stable, comparable snapshot. */\n version: number;\n};\n\n// Shared through a window global: the main entry and the /devtools entry are\n// separate bundles, each with its own copy of this module — module-local\n// state would give the devtools an always-empty registry in published apps.\nconst ssrFallback: RegistryState = {\n components: new Map(),\n slots: new Map(),\n sections: [],\n listeners: new Set(),\n version: 0,\n};\n\nfunction state(): RegistryState {\n if (typeof window === 'undefined') return ssrFallback;\n const w = window as unknown as { __sentient_registry?: RegistryState };\n if (!w.__sentient_registry) {\n w.__sentient_registry = {\n components: new Map(),\n slots: new Map(),\n sections: [],\n listeners: new Set(),\n version: 0,\n };\n }\n return w.__sentient_registry;\n}\n\nfunction emit(): void {\n // Bump BEFORE notifying so a useSyncExternalStore consumer re-reading its\n // snapshot inside the notification sees the new value and re-renders.\n state().version += 1;\n for (const fn of state().listeners) fn();\n}\n\n// The registry exists solely to feed the opt-in devtools panel, which is a\n// dev-only surface. In a production build there is no panel reading it, so\n// every register call is dead work plus a `window.__sentient_registry`\n// footprint on the customer's page. Short-circuit to a noop in production —\n// every <Adaptive>/useAdaptive/slot mount calls one of these.\nconst NOOP_UNREGISTER = (): void => undefined;\n\n/** Register (or re-register) a component. Returns an unregister function. */\nexport function registerComponent(c: RegisteredComponent): () => void {\n if (!isDevBuild()) return NOOP_UNREGISTER;\n state().components.set(c.id, c);\n emit();\n return () => {\n state().components.delete(c.id);\n emit();\n };\n}\n\n/** Register (or re-register) a slot declaration. Returns an unregister function. */\nexport function registerSlot(s: RegisteredSlot): () => void {\n if (!isDevBuild()) return NOOP_UNREGISTER;\n state().slots.set(s.id, s);\n emit();\n return () => {\n state().slots.delete(s.id);\n emit();\n };\n}\n\n/** Register the page's declared section ids (from AdaptiveRoot/provider). */\nexport function registerSections(sections: string[]): void {\n if (!isDevBuild()) return;\n state().sections = [...sections];\n emit();\n}\n\nexport function getRegistered(): RegisteredComponent[] {\n return [...state().components.values()];\n}\n\nexport function getRegisteredSlots(): RegisteredSlot[] {\n return [...state().slots.values()];\n}\n\nexport function getRegisteredSections(): string[] {\n return [...state().sections];\n}\n\nexport function subscribeRegistry(fn: () => void): () => void {\n const listeners = state().listeners;\n listeners.add(fn);\n return () => {\n listeners.delete(fn);\n };\n}\n\n/** Monotonic snapshot for `useSyncExternalStore` — changes on every registry mutation. */\nexport function getRegistryVersion(): number {\n return state().version;\n}\n","'use client';\n\nimport { memo, useEffect, useMemo, useRef, useState, type ReactNode } from 'react';\nimport { attachMicroSignalDetectors, type MicroSignalType } from '@sentientui/core';\nimport { useAdaptiveApiKey, useSentient } from './provider.js';\nimport { useAssignment } from './use-assignment.js';\nimport { registerComponent } from './devtools-registry.js';\n\nexport type {\n ScrollDepthGoal,\n ClickGoal,\n FormSubmitGoal,\n CompositeGoal,\n WeightedStep,\n WeightedCompositeGoal,\n GoalConfig,\n} from './adaptive-shared.js';\nimport { attachGoalListeners, isDevBuild, normalizeGoal, trackExposure, type GoalConfig } from './adaptive-shared.js';\n\n/** Maps a detected micro-signal to a named session goal (`client.goal`). */\nexport type MicroSignalGoalConfig = string | { name: string; weight?: number; stepIndex?: number };\nexport type MicroSignalGoals = Partial<Record<MicroSignalType, MicroSignalGoalConfig>>;\n\nexport type AdaptiveProps = {\n id: string;\n variants: Record<string, ReactNode>;\n goal: string | GoalConfig;\n /**\n * When a passive micro-signal fires on this component, also record a named goal.\n * Use for inferred goals surfaced in the dashboard (e.g. rage_click → 'confused_by_hero').\n */\n microSignalGoals?: MicroSignalGoals;\n /**\n * When true, renders nothing during SSR and before client hydration.\n * Use when you cannot pass `initialAssignments` and prefer a blank slot over\n * a hydration mismatch. Tradeoff: minor CLS on first paint.\n */\n clientOnly?: boolean;\n /**\n * Variant-specific structured data for AI agent consumption via /sentient.json and\n * GET /v1/agent/layout. Keyed by variant ID — only the assigned variant's entry is stored,\n * so agents see only the content currently being served to visitors.\n *\n * Prefer this over `agentData` when variants have meaningfully different content.\n *\n * Captured at MOUNT: this value is read once, when the component's assignment\n * is requested, and is intentionally not part of the assign effect's deps.\n * Changing it after mount does not re-send it — pass the final value on first\n * render (e.g. from SSR/loader data, not a value that streams in later).\n */\n agentDataByVariant?: Record<string, unknown>;\n /**\n * @deprecated Use agentDataByVariant for variant-specific content. Stored as-is for the assigned variant.\n *\n * Captured at MOUNT (see `agentDataByVariant`): changing it after mount has no\n * effect on what is sent for the assignment.\n */\n agentData?: unknown;\n};\n\nfunction AdaptiveImpl(props: AdaptiveProps): JSX.Element | null {\n const client = useSentient();\n const apiKey = useAdaptiveApiKey();\n // Freeze the variant-id array on the KEY SET, not the object identity: an\n // inline `variants={{...}}` literal is a fresh object every render, so keying\n // on `props.variants` churned a new array each commit — re-running the\n // register effect (dep below) and unregistering+re-registering the component\n // on every render. A joined-keys signature is stable across renders for the\n // same keys yet still updates if the declared set changes. Same convention as\n // useAdaptive / AdaptiveGroup / useAdaptiveTokens.\n const variantKey = Object.keys(props.variants).join('\\u0000');\n // eslint-disable-next-line react-hooks/exhaustive-deps\n const variantIds = useMemo(() => Object.keys(props.variants), [variantKey]);\n const { variantId, content, isOverride, settled } = useAssignment(props.id, variantIds, props.agentData, props.agentDataByVariant);\n const containerRef = useRef<HTMLDivElement>(null);\n const [mounted, setMounted] = useState(false);\n\n useEffect(() => { setMounted(true); }, []);\n const goalFiredRef = useRef(false);\n const microGoalFiredRef = useRef<Set<MicroSignalType>>(new Set());\n const assignTrackedRef = useRef<string | null>(null);\n const goalKey = typeof props.goal === 'string' ? props.goal : JSON.stringify(props.goal);\n const goal = useMemo(() => normalizeGoal(props.goal), [goalKey]);\n const goalLabel = typeof props.goal === 'string' ? props.goal : goal.type;\n\n // Register with the devtools registry so the dev widget can list this\n // component + its variants. Inert in production (registry has no UI); the\n // cleanup unregisters on unmount.\n useEffect(() => registerComponent({ id: props.id, variantIds, goal: goalLabel }), [props.id, variantIds, goalLabel]);\n\n // Track variant_assigned exactly once per (component, variant) mount.\n useEffect(() => {\n // A forced variant is a dev/test view, not a real exposure — recording it\n // would train the bandit on the override. Same gate on every tracking\n // effect below (\"no events recorded, weights unchanged\").\n if (isOverride) return;\n // Only expose a SETTLED assignment. On the CSR path the served variant\n // resolves in two steps (interim baseline variantIds[0] → bandit choice);\n // tracking the interim would accrue a phantom baseline exposure that can\n // never convert. Mirrors AdaptiveText (start null, track after settle).\n if (!settled) return;\n if (!client || !variantId || !apiKey) return;\n if (assignTrackedRef.current === variantId) return;\n assignTrackedRef.current = variantId;\n trackExposure(client, apiKey, props.id, variantId);\n }, [client, variantId, apiKey, props.id, isOverride, settled]);\n\n // Reset goal latch when variant or goal changes.\n useEffect(() => {\n goalFiredRef.current = false;\n microGoalFiredRef.current = new Set();\n }, [variantId, goal]);\n\n // Emit cursor_signal after 800 ms of continuous hover.\n useEffect(() => {\n if (isOverride) return;\n // Same settle gate as the exposure: before assign() resolves, variantId is\n // the interim baseline placeholder — a hover then would attribute a\n // cursor_signal to an arm that was never really served.\n if (!settled) return;\n if (!client || !variantId) return;\n const node = containerRef.current;\n if (!node) return;\n\n let timerId: ReturnType<typeof setTimeout> | null = null;\n let hoverStart = 0;\n\n const onEnter = (): void => {\n hoverStart = Date.now();\n timerId = setTimeout(() => {\n client.track({\n projectId: apiKey,\n componentId: props.id,\n variantId: variantId!,\n eventType: 'cursor_signal',\n payload: { hoverDuration: Date.now() - hoverStart },\n });\n timerId = null;\n }, 800);\n };\n\n const onLeave = (): void => {\n if (timerId !== null) {\n clearTimeout(timerId);\n timerId = null;\n }\n };\n\n node.addEventListener('mouseenter', onEnter);\n node.addEventListener('mouseleave', onLeave);\n return () => {\n node.removeEventListener('mouseenter', onEnter);\n node.removeEventListener('mouseleave', onLeave);\n if (timerId !== null) clearTimeout(timerId);\n };\n }, [client, variantId, apiKey, props.id, isOverride, settled]);\n\n // Attach micro-signal detectors passively — rage click, text copy, scroll hesitation, tab loss.\n useEffect(() => {\n if (isOverride) return;\n // Gate on settle too (like the exposure): during the pre-assign() window\n // variantId is the interim baseline placeholder, so a rage-click / tab-loss\n // would record a micro_signal — and fire a mapped named goal — attributed\n // to an arm that was never really served.\n if (!settled) return;\n if (!client || !variantId) return;\n const node = containerRef.current;\n if (!node) return;\n const assignedAt = Date.now();\n return attachMicroSignalDetectors(\n (signalType, extra = {}) => {\n client.track({\n projectId: apiKey,\n componentId: props.id,\n variantId: variantId!,\n eventType: 'micro_signal',\n payload: { signalType, ...extra },\n });\n\n const mapping = props.microSignalGoals?.[signalType];\n if (!mapping || microGoalFiredRef.current.has(signalType)) return;\n microGoalFiredRef.current.add(signalType);\n const name = typeof mapping === 'string' ? mapping : mapping.name;\n const weight = typeof mapping === 'string' ? 1.0 : (mapping.weight ?? 1.0);\n const stepIndex = typeof mapping === 'string' ? 0 : (mapping.stepIndex ?? 0);\n client.goal(name, { signalType, ...extra }, weight, stepIndex);\n },\n node,\n assignedAt,\n );\n }, [client, variantId, apiKey, props.id, props.microSignalGoals, isOverride, settled]);\n\n // Attach goal tracking (shared machinery — see adaptive-shared.ts).\n useEffect(() => {\n if (isOverride) return;\n if (!client || !variantId) return;\n const node = containerRef.current;\n if (!node) return;\n\n return attachGoalListeners(node, goal, {\n fireGoal: () => {\n if (goalFiredRef.current) return;\n goalFiredRef.current = true;\n client.track({\n projectId: apiKey,\n componentId: props.id,\n variantId,\n eventType: 'goal_achieved',\n goalType: goalLabel,\n payload: { reward: 1.0 },\n });\n client.goal(goalLabel, { componentId: props.id, variantId }, 1.0, 0);\n },\n fireStep: (name, weight, stepIndex) => {\n client.track({\n projectId: apiKey,\n componentId: props.id,\n variantId: variantId!,\n eventType: 'goal_achieved',\n goalType: name,\n payload: { reward: weight },\n });\n client.goal(name, {}, weight, stepIndex);\n },\n });\n }, [client, variantId, apiKey, props.id, goal, goalLabel, isOverride]);\n\n // Decorative slots: empty in SSR HTML and until the client has mounted.\n if (props.clientOnly && (!mounted || !client)) return null;\n if (!variantId) return null;\n\n const jsxContent = props.variants[variantId] ?? null;\n const managedContent = jsxContent === null ? content : null;\n\n if (isDevBuild() && jsxContent === null && managedContent === null) {\n console.warn(\n `[sentient] <Adaptive id=\"${props.id}\"> was assigned variant \"${variantId}\" but no matching key exists in props.variants.` +\n ` If this is a dashboard-managed text variant, use <AdaptiveText id=\"${props.id}\"> instead.`,\n );\n }\n\n return (\n <div ref={containerRef} data-sentient-id={props.id} data-sentient-variant={variantId}>\n {jsxContent ?? managedContent}\n </div>\n );\n}\n\n/**\n * Skips re-render only when nothing the output depends on has changed. The\n * variant node values must be compared, not just their keys: the assigned\n * `variantId` is stable, so if we compared keys alone, dynamic content inside a\n * variant (e.g. `<Price value={price}/>`) would render once and then freeze when\n * `price` changes. Elements are compared by reference — a caller that recreates\n * variant JSX on every render re-renders every time (correct), while stable/\n * memoized elements keep the optimization.\n */\nexport const Adaptive = memo(AdaptiveImpl, (prev, next) => {\n if (prev.id !== next.id) return false;\n // Serialize only when the goal reference actually changed — a stable/memoized\n // goal (the common case) skips the stringify entirely.\n if (prev.goal !== next.goal && JSON.stringify(prev.goal) !== JSON.stringify(next.goal)) return false;\n if (prev.microSignalGoals !== next.microSignalGoals) return false;\n if (prev.clientOnly !== next.clientOnly) return false;\n if (prev.agentData !== next.agentData) return false;\n if (prev.agentDataByVariant !== next.agentDataByVariant) return false;\n if (prev.variants === next.variants) return true;\n const prevKeys = Object.keys(prev.variants);\n const nextKeys = Object.keys(next.variants);\n if (prevKeys.length !== nextKeys.length) return false;\n return prevKeys.every((k) => k in next.variants && Object.is(prev.variants[k], next.variants[k]));\n});\n","import { useEffect, useRef, useState, useSyncExternalStore } from 'react';\nimport { type AssignResult } from '@sentientui/core';\nimport { useSentient, useInitialAssignments, useSessionSegment, useSsrFallback, useOnAssignment, useDebug } from './provider.js';\nimport { subscribe, getWeights, type ComponentWeights } from './weights-store.js';\nimport { subscribeOverridesChanged } from './override-events.js';\nimport { getDevOverride } from './dev-override.js';\n\nexport type AssignmentState = {\n variantId: string | null;\n /** Populated when the assigned variant is a dashboard-managed text variant. */\n content: string | null;\n isLoading: boolean;\n /**\n * True once `variantId` reflects a REAL decision — an SSR preload, the local\n * assignment cache, a server `assign()`, live bandit weights, or a dev\n * override — rather than the interim `variantIds[0]` placeholder shown while a\n * decision is still in flight. Exposure tracking MUST gate on this: emitting\n * `variant_assigned` for the placeholder accrues a phantom baseline\n * impression that can never convert and dilutes that arm's CVR.\n */\n settled: boolean;\n /**\n * True while a dev override (?sentient_variant= / window.__sentient_overrides)\n * is forcing this variant. Consumers must suppress ALL tracking while set —\n * the override contract is \"no events recorded, weights unchanged\".\n */\n isOverride?: boolean;\n};\n\n// Pseudo-count for the shrinkage prior below — the number of \"prior\" pulls at\n// reward 0 mixed into every arm's mean. Large enough to sink a lucky 1-pull\n// arm, small enough to be negligible once an arm has real traffic.\nconst PRIOR_PULLS = 5;\n\n/**\n * Degraded-fallback selection from cached bandit weights (used only when the\n * server assignment hasn't resolved). Ranks arms by a posterior mean shrunk\n * toward a zero prior — `pulls·avgReward / (pulls + PRIOR_PULLS)` — so a lucky\n * small-sample arm (e.g. 1 pull at avgReward 1.0) can't outrank a well-sampled\n * one (500 pulls at 0.2). With equal pulls the shrinkage is monotonic in\n * avgReward, preserving plain \"highest avgReward wins\" behavior.\n */\nfunction pickFromWeights(weights: ComponentWeights, variantIds: string[]): string | null {\n let best: { variantId: string; score: number } | null = null;\n for (const v of weights.variants) {\n if (!variantIds.includes(v.variantId)) continue;\n const pulls = v.pulls ?? 0;\n const score = pulls > 0 ? (pulls * v.avgReward) / (pulls + PRIOR_PULLS) : 0;\n if (!best || score > best.score) {\n best = { variantId: v.variantId, score };\n }\n }\n return best?.variantId ?? null;\n}\n\n/**\n * Returns a sticky variant assignment for a component.\n *\n * @deprecated Since 0.13.0 — use {@link useAdaptive} instead. `useAssignment`\n * only SELECTS a variant; it wires no exposure tracking, no goal listeners,\n * and no micro-signals, so components using it directly accumulate no\n * learning signal. It keeps working (it is `useAdaptive`'s internal\n * selection engine) but will move to internal-only in 1.0.0.\n *\n * First render reads the local SDK cache; if empty, falls back to a\n * deterministic default and asynchronously calls `/v1/assign`. The server\n * picks the actual variant via Thompson Sampling and the result replaces the fallback\n * on the next render. Subsequent paints read synchronously from cache —\n * no flicker, no loading state after first paint.\n */\nexport function useAssignment(componentId: string, variantIds: string[], agentData?: unknown, agentDataByVariant?: Record<string, unknown>): AssignmentState {\n const initialAssignments = useInitialAssignments();\n const ssrFallback = useSsrFallback();\n const client = useSentient();\n const segment = useSessionSegment();\n const onAssignment = useOnAssignment();\n const debug = useDebug();\n const assignmentReportedRef = useRef<string | null>(null);\n\n // Dev override (URL ?sentient_variant=componentId:variantId or\n // window.__sentient_overrides[componentId]) read through useSyncExternalStore:\n // - server snapshot is null (no window), so SSR renders the un-forced variant;\n // - the client snapshot reads the override, and React reconciles the two\n // across hydration WITHOUT a mismatch (this is exactly what the hook is for);\n // - unlike a post-mount flip it is already correct on a remount / CSR-nav, so\n // a forced variant never leaks an interim assign() or exposure before the\n // override applies.\n // It also re-renders when the devtools/scenario helpers bump the override bus.\n const devOverride = useSyncExternalStore(\n subscribeOverridesChanged,\n () => getDevOverride(componentId),\n () => null,\n );\n const overrideVariant = devOverride && variantIds.includes(devOverride) ? devOverride : null;\n const overrideLoggedRef = useRef<string | null>(null);\n // Diagnostic log for an active dev override — effect, never render body, and\n // gated behind the provider's debug flag so it stays silent in production.\n useEffect(() => {\n if (!debug) return;\n if (!overrideVariant) return;\n if (overrideLoggedRef.current === overrideVariant) return;\n overrideLoggedRef.current = overrideVariant;\n console.info(`[sentient] override active: ${componentId} -> ${overrideVariant}`);\n }, [debug, overrideVariant, componentId]);\n\n // Lazy initializer: this selection logic (URLSearchParams parse via the\n // override read above, cache + weights Map lookups) runs ONCE on mount, not\n // on every render. React only uses a useState initializer's value on first\n // render, so computing it eagerly each render was pure waste on every\n // <Adaptive>/useAdaptive re-render. Mirrors AdaptiveText's lazy seeds.\n const [state, setState] = useState<AssignmentState>((): AssignmentState => {\n if (overrideVariant) {\n return { variantId: overrideVariant, content: null, isLoading: false, settled: true };\n }\n // SSR / pre-hydration: no client yet. Use initialAssignments if provided so\n // the server and client first render agree on the same variant (no mismatch).\n if (!client) {\n const preloaded = initialAssignments[componentId];\n if (preloaded && variantIds.includes(preloaded)) {\n // Server-decided — a real assignment, safe to expose.\n return { variantId: preloaded, content: null, isLoading: false, settled: true };\n }\n if (ssrFallback === 'first' && variantIds.length > 0) {\n // SEO placeholder shown until the client resolves a real decision — NOT\n // settled, so no exposure fires for this interim baseline.\n return { variantId: variantIds[0], content: null, isLoading: false, settled: false };\n }\n return { variantId: null, content: null, isLoading: true, settled: false };\n }\n const cached = client.getAssignment(componentId, segment);\n // Allow cached managed variants (content present) even if not in variantIds.\n if (cached && (variantIds.includes(cached.variantId) || cached.content)) {\n return { variantId: cached.variantId, content: cached.content ?? null, isLoading: false, settled: true };\n }\n const weights = getWeights(componentId);\n if (weights) {\n const chosen = pickFromWeights(weights, variantIds);\n if (chosen) return { variantId: chosen, content: null, isLoading: false, settled: true };\n }\n // Interim placeholder while the async assign() below is in flight — not a\n // real decision yet, so it stays unsettled and emits no exposure.\n return { variantId: variantIds[0] ?? null, content: null, isLoading: false, settled: false };\n });\n\n // Helper: call onAssignment at most once per resolved variant.\n const reportAssignment = (variantId: string): void => {\n if (!onAssignment) return;\n if (assignmentReportedRef.current === variantId) return;\n assignmentReportedRef.current = variantId;\n onAssignment(componentId, variantId);\n };\n\n // As soon as the client is ready, unblock the UI immediately with variantIds[0]\n // (or a cached value) so the component never stays invisible while assign is\n // in-flight. The async assign call below then swaps to the bandit-chosen variant.\n useEffect(() => {\n if (overrideVariant) return;\n if (!client) return;\n const cached = client.getAssignment(componentId, segment);\n if (cached && (variantIds.includes(cached.variantId) || cached.content)) {\n setState({ variantId: cached.variantId, content: cached.content ?? null, isLoading: false, settled: true });\n reportAssignment(cached.variantId);\n return;\n }\n setState((prev) => prev.variantId ? prev : { variantId: variantIds[0] ?? null, content: null, isLoading: false, settled: false });\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [overrideVariant, client, componentId, segment]);\n\n // Ask the server for a real assignment when we have a client but no cached one.\n useEffect(() => {\n if (overrideVariant) return;\n if (!client) return;\n const cached = client.getAssignment(componentId, segment);\n if (cached && variantIds.includes(cached.variantId)) return;\n\n let cancelled = false;\n void client.assign(componentId, variantIds, agentData, agentDataByVariant).then((result: AssignResult | null) => {\n if (cancelled) return;\n if (!result) return;\n // Allow the result if it's a known code variant OR a managed text variant (has content).\n if (!variantIds.includes(result.variantId) && !result.content) return;\n setState({ variantId: result.variantId, content: result.content ?? null, isLoading: false, settled: true });\n reportAssignment(result.variantId);\n });\n return () => { cancelled = true; };\n // variantIds intentionally excluded — changing variants mid-mount is unsupported\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [overrideVariant, client, componentId, segment]);\n\n // Live weight updates from the dashboard SSE stream (when wired).\n useEffect(() => {\n if (overrideVariant) return;\n if (!client) return;\n return subscribe(componentId, (weights) => {\n const cached = client.getAssignment(componentId, segment);\n if (cached && (variantIds.includes(cached.variantId) || cached.content)) {\n setState({ variantId: cached.variantId, content: cached.content ?? null, isLoading: false, settled: true });\n return;\n }\n const chosen = pickFromWeights(weights, variantIds);\n if (chosen) setState({ variantId: chosen, content: null, isLoading: false, settled: true });\n });\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [overrideVariant, client, componentId, segment]);\n\n if (overrideVariant) {\n return { variantId: overrideVariant, content: null, isLoading: false, settled: true, isOverride: true };\n }\n\n return state;\n}\n","declare global {\n interface Window {\n __sentient_overrides?: Record<string, string>;\n }\n}\n\n/**\n * Reads a forced variant for a component from the dev-override channels:\n * `window.__sentient_overrides[id]` (devtools panel, `applyScenario`, the\n * Playwright/Cypress helpers) or the `?sentient_variant=id:variant` URL param\n * (repeatable for multiple components). Returns `null` in non-browser envs.\n *\n * Callers MUST read this POST-MOUNT (never in the render body): it touches\n * `window.location`, which is absent on the server, so reading it during render\n * diverges the SSR output from the client's first render and throws a hydration\n * mismatch on any SSR page carrying `?sentient_variant=`.\n */\nexport function getDevOverride(componentId: string): string | null {\n if (typeof window === 'undefined') return null;\n const global = window.__sentient_overrides?.[componentId];\n if (global) return global;\n // This runs as a useSyncExternalStore getSnapshot (once or twice per render\n // pass, per adaptive component), so skip the URLSearchParams parse entirely on\n // the overwhelmingly common no-query-string page.\n if (!window.location.search) return null;\n try {\n const params = new URLSearchParams(window.location.search);\n for (const raw of params.getAll('sentient_variant')) {\n // sentient_variant=componentId:variantId (repeatable for multiple components)\n const sep = raw.indexOf(':');\n if (sep === -1) continue;\n if (raw.slice(0, sep) === componentId) return raw.slice(sep + 1);\n }\n } catch {\n /* non-browser env */\n }\n return null;\n}\n","'use client';\n\nimport { useEffect, useMemo, useRef, useState, useSyncExternalStore, type ElementType } from 'react';\nimport type { AssignResult } from '@sentientui/core';\nimport { useSentient, useAdaptiveApiKey, useOnAssignment, useSessionSegment } from './provider.js';\nimport { attachGoalListeners, isDevBuild, normalizeGoal, type GoalConfig } from './adaptive-shared.js';\nimport { getDevOverride } from './dev-override.js';\nimport { subscribeOverridesChanged } from './override-events.js';\n\n\nexport type AdaptiveTextProps = {\n id: string;\n default: string;\n component?: keyof JSX.IntrinsicElements;\n className?: string;\n /**\n * Optional conversion goal to optimize this copy toward. Without it, the\n * variant is served and logged but never scored — the copy rotates and never\n * learns. Provide a goal (a name string or a GoalConfig) to make the optimizer\n * attribute conversions to the winning wording, exactly like `<Adaptive>`.\n */\n goal?: string | GoalConfig;\n};\n\n/**\n * Dashboard-managed copy for a single element. The variants are **text only** —\n * they change the wording, never the CSS, markup, or layout of the element\n * (managed variants created from the dashboard/MCP carry text, nothing else).\n * For anything structural — style, markup shape, position — write the change in\n * code with `<Adaptive>` (any JSX per variant) or use adaptive slots on no-code\n * sites. Pass `goal` to make the managed copy optimizable (see below).\n */\nexport function AdaptiveText({\n id,\n default: defaultText,\n component: Tag = 'span',\n className,\n goal: goalProp,\n}: AdaptiveTextProps) {\n const client = useSentient();\n const apiKey = useAdaptiveApiKey();\n const onAssignment = useOnAssignment();\n const segment = useSessionSegment();\n const trackedRef = useRef<string | null>(null);\n const nodeRef = useRef<HTMLElement | null>(null);\n\n // Dev override parity with <Adaptive>/useAdaptive: honor\n // ?sentient_variant=id:variant and window.__sentient_overrides (devtools,\n // applyScenario, Playwright/Cypress). A forced variant is a preview — it\n // suppresses the network assign, exposure, and goals (\"no events recorded,\n // weights unchanged\"). Read through useSyncExternalStore (server snapshot\n // null → no hydration mismatch on a ?sentient_variant= page; client snapshot\n // synchronous → no interim assign() before the override applies on remount).\n const override = useSyncExternalStore(\n subscribeOverridesChanged,\n () => getDevOverride(id),\n () => null,\n );\n\n // Seed from cache synchronously so remounts don't flash back to defaultText.\n const [text, setText] = useState<string | null>(() =>\n client?.getAssignment(id, segment)?.content ?? null\n );\n const [variantId, setVariantId] = useState<string | null>(() =>\n client?.getAssignment(id, segment)?.variantId ?? null\n );\n\n useEffect(() => {\n if (override) return; // forced variant — no network assign\n if (!client) return;\n // Skip if content already cached; assign() re-checks internally but this avoids the async round-trip on remount.\n if (client.getAssignment(id, segment)?.content !== undefined) return;\n\n let cancelled = false;\n void client.assign(id).then((result: AssignResult | null) => {\n if (cancelled) return;\n if (!result) {\n if (isDevBuild()) {\n console.warn(`[sentient] <AdaptiveText id=\"${id}\"> assignment failed — showing default text.`);\n }\n return;\n }\n setVariantId(result.variantId);\n if (result.content) setText(result.content);\n });\n return () => {\n cancelled = true;\n };\n }, [client, id, segment, override]);\n\n useEffect(() => {\n if (override) return; // forced variant records no exposure\n if (!client || !variantId || !apiKey) return;\n if (trackedRef.current === variantId) return;\n trackedRef.current = variantId;\n client.track({\n projectId: apiKey,\n componentId: id,\n variantId,\n eventType: 'variant_assigned',\n payload: {},\n });\n onAssignment?.(id, variantId);\n }, [client, variantId, apiKey, id, onAssignment, override]);\n\n // Optional goal attribution (opt-in) — mirrors <Adaptive>. Without a goal the\n // copy is served but never scored.\n const goalKey = goalProp === undefined ? '' : typeof goalProp === 'string' ? goalProp : JSON.stringify(goalProp);\n const goal = useMemo(() => (goalProp === undefined ? null : normalizeGoal(goalProp)), [goalKey]);\n const goalLabel = goalProp === undefined ? null : typeof goalProp === 'string' ? goalProp : goal!.type;\n const goalFiredRef = useRef(false);\n\n useEffect(() => {\n goalFiredRef.current = false;\n }, [variantId, goalKey]);\n\n useEffect(() => {\n if (override) return; // forced variant records no goals\n if (!client || !variantId || !apiKey || !goal || !goalLabel) return;\n const node = nodeRef.current;\n if (!node) return;\n return attachGoalListeners(node, goal, {\n fireGoal: () => {\n if (goalFiredRef.current) return;\n goalFiredRef.current = true;\n client.track({\n projectId: apiKey,\n componentId: id,\n variantId,\n eventType: 'goal_achieved',\n goalType: goalLabel,\n payload: { reward: 1.0 },\n });\n client.goal(goalLabel, { componentId: id, variantId }, 1.0, 0);\n },\n fireStep: (name, weight, stepIndex) => {\n client.track({\n projectId: apiKey,\n componentId: id,\n variantId,\n eventType: 'goal_achieved',\n goalType: name,\n payload: { reward: weight },\n });\n client.goal(name, {}, weight, stepIndex);\n },\n });\n }, [client, variantId, apiKey, id, goal, goalLabel, override]);\n\n // Under a forced override, show the override variant's managed copy only if\n // it happens to be cached (managed text lives server-side, so an arbitrary\n // forced variant has no client-available copy) — otherwise fall back to the\n // default. Without an override this is just the assigned/default text.\n let displayText = text ?? defaultText;\n if (override) {\n const cached = client?.getAssignment(id, segment);\n displayText = cached && cached.variantId === override ? (cached.content ?? defaultText) : defaultText;\n }\n\n // Cast to ElementType so a single ref callback works across every intrinsic\n // tag without exploding into the full HTML/SVG ref union.\n const Component = Tag as ElementType;\n return (\n <Component ref={(el: HTMLElement | null) => { nodeRef.current = el; }} className={className}>\n {displayText}\n </Component>\n );\n}\n","import { useCallback } from 'react';\nimport type { ComponentGoalOptions } from '@sentientui/core';\nimport { useSentient } from './provider.js';\nimport { getDevOverride } from './dev-override.js';\n\nexport type FireGoal = (goalType: string, opts?: ComponentGoalOptions) => void;\n\n/**\n * Returns a `fireGoal(goalType, opts?)` callback that records a conversion\n * attributed to the variant currently served for `componentId` — so it shows\n * up in the per-variant CVR funnel with no manual variantId/projectId plumbing.\n *\n * The served variant is resolved from the SDK's assignment cache (the same one\n * `<Adaptive id={componentId}>` populates), so render that component before\n * firing. Use this for imperative handlers (click, form submit, custom events);\n * for purely declarative goals prefer `<Adaptive goal={...}>`.\n *\n * Each call records one bandit reward event AND one session goal-funnel record.\n * It has no cross-call latch, so a component that *also* declares a matching\n * `<Adaptive goal>` (or fires this on every click) records one conversion per\n * call — keep goal labels unique per conversion so counts aren't inflated.\n *\n * @example\n * const fireContact = useAdaptiveGoal('hero_headline');\n * <button onClick={() => fireContact('hero_contact', { metadata: { method } })}>Call</button>\n */\nexport function useAdaptiveGoal(componentId: string): FireGoal {\n const client = useSentient();\n return useCallback<FireGoal>(\n (goalType, opts) => {\n // A forced variant (?sentient_variant= / window.__sentient_overrides) is a\n // dev/QA preview, not real traffic. Recording a goal would credit the\n // bandit and pollute the session funnel for the overridden arm — breaking\n // the \"no events recorded, weights unchanged\" override contract that\n // <Adaptive>, useAdaptive.fireGoal, and the declarative path all honor.\n // Read post-mount (inside the callback), never in a render body.\n if (getDevOverride(componentId)) return;\n // componentGoal credits the bandit (arm resolved from the assignment\n // cache); goal() writes the session-level conversion funnel record. A\n // declared <Adaptive goal> fires both — a manual conversion for the same\n // component must too, or it shows up in per-variant CVR but never in the\n // session goal funnel.\n client?.componentGoal(componentId, goalType, opts);\n client?.goal(goalType, opts?.metadata ?? {}, opts?.reward ?? 1.0, 0);\n },\n [client, componentId],\n );\n}\n","import { renderPrePaintScript } from '@sentientui/core';\nimport { confidenceBand } from '@sentientui/policy';\n\nexport type SentientPersonaScriptProps = {\n /** Publishable API key — selects the localStorage snapshot in the fallback path. */\n apiKey: string;\n /**\n * CSP nonce for the inline pre-paint script. Pass the same nonce your\n * `Content-Security-Policy` `script-src` allows (e.g. from Next.js middleware).\n * Required for strict CSP deployments that block `'unsafe-inline'`.\n */\n nonce?: string;\n /**\n * SSR-decided persona (from `loadAdaptiveDecision`). When present the\n * script embeds the literal values; when absent it reads the local\n * decision snapshot (SPA / return-visit path).\n */\n persona?: { persona: string; confidence: number } | null;\n};\n\n/** JSON string literal that is also safe inside an inline <script> element. */\nfunction inlineJsString(value: string): string {\n return JSON.stringify(value).replace(/</g, '\\\\u003c');\n}\n\n/** Exported for tests. Builds the inline JS (concatenation only — no backticks). */\nexport function personaScriptBody(props: SentientPersonaScriptProps): string {\n if (props.persona) {\n return (\n '(function(){try{var d=document.documentElement;' +\n 'if(d.hasAttribute(\"data-sentient-persona\"))return;' +\n 'd.setAttribute(\"data-sentient-persona\",' + inlineJsString(props.persona.persona) + ');' +\n 'd.setAttribute(\"data-sentient-confidence\",' + inlineJsString(confidenceBand(props.persona.confidence)) + ');' +\n '}catch(e){}})();'\n );\n }\n return renderPrePaintScript(props.apiKey);\n}\n\n/**\n * Single writer of the Rung-1a `<html>` attributes\n * (`data-sentient-persona`, `data-sentient-confidence`), executed pre-paint.\n *\n * `AdaptiveRoot` renders this automatically as its first child. For Pages\n * Router / Remix, render it yourself in `_document` / the root layout.\n *\n * IMPORTANT (install docs): add `suppressHydrationWarning` to your `<html>`\n * element — this script mutates documentElement before React hydrates it\n * (the same pattern next-themes uses). The client SDK adopts the attributes\n * as truth and never rewrites them mid-session.\n */\nexport function SentientPersonaScript(props: SentientPersonaScriptProps): JSX.Element {\n return (\n <script\n data-sentient-persona-script=\"\"\n nonce={props.nonce}\n dangerouslySetInnerHTML={{ __html: personaScriptBody(props) }}\n />\n );\n}\n","import { useEffect, useMemo, useRef } from 'react';\nimport type { SlotDeclInput } from '@sentientui/core';\nimport { validateSlotDecl } from '@sentientui/policy';\nimport { useAdaptiveApiKey, useSentient } from './provider.js';\nimport { useSlotResult } from './use-slot-result.js';\nimport { registerSlot } from './devtools-registry.js';\nimport {\n attachGoalListeners,\n goalLabelOf,\n isDevBuild,\n normalizeGoal,\n trackExposure,\n type GoalConfig,\n} from './adaptive-shared.js';\n\nexport type UseAdaptiveTokensOptions = { goal?: string | GoalConfig };\nexport type UseAdaptiveTokensResult = {\n tokens: Record<string, string>;\n /** Spread on the slot's element: `data-<dim>` per dim + `data-sentient-slot`. */\n props: Record<string, string>;\n};\n\n// Warn once per slot id per page lifetime — not per render.\nconst warnedTokenSlots = new Set<string>();\n\nfunction cssEscape(value: string): string {\n if (typeof CSS !== 'undefined' && typeof CSS.escape === 'function') return CSS.escape(value);\n // Fallback for environments without CSS.escape: the value is interpolated\n // inside a double-quoted attribute selector (`[data-sentient-slot=\"…\"]`), so\n // both the backslash and the closing quote must be escaped — the old\n // quote-only escape let a slot id containing `\\` break out of the selector\n // (and an unescaped `\"` in a since-fixed path could match the wrong node).\n return value.replace(/[\\\\\"]/g, '\\\\$&');\n}\n\n/**\n * Rung 1b — adaptive design tokens. Declares a bounded token space; the\n * optimizer picks per persona; values apply as element-scoped data\n * attributes so they serialize through SSR markup (zero flicker,\n * hydration-safe). First value of each dim = baseline.\n *\n * ```tsx\n * const t = useAdaptiveTokens('hero', { tone: ['calm', 'urgent'] });\n * return <section {...t.props} className=\"hero\">…</section>;\n * // CSS: .hero[data-tone=\"urgent\"] .cta { … }\n * ```\n */\nexport function useAdaptiveTokens(\n id: string,\n dims: Record<string, readonly string[]>,\n opts?: UseAdaptiveTokensOptions,\n): UseAdaptiveTokensResult {\n const client = useSentient();\n const apiKey = useAdaptiveApiKey();\n\n // Freeze the declaration on the DIMS SIGNATURE, not the object identity: an\n // inline `dims={{...}}` literal is a fresh object each render, so keying on it\n // would churn a new decl every commit. A stringified signature is stable\n // across renders for the same dims yet updates if the declared space changes\n // (same convention as <Adaptive> / useAdaptive / AdaptiveGroup). A slot's\n // declared space is normally fixed for the session.\n const dimsKey = JSON.stringify(dims);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n const decl = useMemo<SlotDeclInput>(() => ({ id, dims }), [id, dimsKey]);\n const { result, arm, source } = useSlotResult(id, decl);\n const tokens = useMemo<Record<string, string>>(\n () => (typeof result === 'string' ? {} : result),\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [arm],\n );\n\n if (isDevBuild() && !warnedTokenSlots.has(id)) {\n const validity = validateSlotDecl({\n id,\n dims: Object.fromEntries(Object.entries(dims).map(([k, v]) => [k, [...v]])),\n });\n const space = Object.values(dims).reduce((n, values) => n * values.length, 1);\n if (!validity.ok) {\n warnedTokenSlots.add(id);\n console.warn(\n `[sentient] useAdaptiveTokens(\"${id}\"): invalid declaration — ${validity.reason}. Serving baseline.`,\n );\n } else if (space > 4) {\n warnedTokenSlots.add(id);\n console.warn(\n `[sentient] useAdaptiveTokens(\"${id}\") declares ${space} combinations — more than the recommended 4. Each extra combination needs more traffic to learn; consider fewer dims/values.`,\n );\n }\n }\n\n const goalKey =\n opts?.goal === undefined ? null : typeof opts.goal === 'string' ? opts.goal : JSON.stringify(opts.goal);\n\n // Devtools slot registry — the declared dims space drives both persona\n // simulation and the panel's per-dim override buttons. A slot is NOT a\n // component: registering it as one produced buttons that wrote the wrong\n // override channel (`__sentient_overrides` instead of `__sentient_slot_overrides`).\n // eslint-disable-next-line react-hooks/exhaustive-deps\n useEffect(() => registerSlot({ id, dims }), [id]);\n\n // Exposure — the slot equivalent of <Adaptive>'s variant_assigned event,\n // once per (slot, arm). variantId = canonical arm string.\n const exposedArmRef = useRef<string | null>(null);\n useEffect(() => {\n // Don't expose an unresolved baseline: a `baseline` source means the slot\n // was never decided (interim local decide, or a keyed client with no SSR\n // preload). Recording it accrues a phantom baseline impression that can\n // never convert. Once a real arm resolves (source flips to preloaded/\n // client) the exposure fires for that arm.\n // A forced arm (`override`, from devtools/tests) is a preview, not a real\n // exposure — recording it would train the optimizer on the override, the\n // same \"no events, weights unchanged\" contract <Adaptive> honors for\n // component overrides.\n if (!client || source === 'baseline' || source === 'override' || exposedArmRef.current === arm) return;\n exposedArmRef.current = arm;\n trackExposure(client, apiKey, id, arm);\n }, [client, apiKey, id, arm, source]);\n\n // Optional goal: the returned props carry data-sentient-slot, so the slot's\n // element is findable without a ref (the pinned return type has no ref).\n // Credit flows through componentGoal(slot id) — the core resolves the\n // attributed arm from its slot state (Task 3.3 fallback).\n useEffect(() => {\n // Forced arms record nothing (preview only) — same gate as the exposure.\n if (!client || !opts?.goal || source === 'override') return;\n const node = document.querySelector(`[data-sentient-slot=\"${cssEscape(id)}\"]`);\n if (!node) {\n if (isDevBuild()) {\n console.warn(\n `[sentient] useAdaptiveTokens(\"${id}\"): a goal is declared but no element carries the returned props — spread {...props} on the slot's element.`,\n );\n }\n return;\n }\n const label = goalLabelOf(opts.goal);\n let fired = false;\n return attachGoalListeners(node, normalizeGoal(opts.goal), {\n fireGoal: () => {\n if (fired) return;\n fired = true;\n // componentGoal credits the bandit (goal_achieved event, arm resolved\n // from slot state); goal() writes the session-level conversion funnel\n // record — exactly what <Adaptive> does for component goals. Slots\n // fired only the former, so slot conversions were invisible in the\n // goal funnel; fire both so membership matches components. (One funnel\n // record per conversion — see useAdaptiveGoal; keep labels unique.)\n client.componentGoal(id, label);\n client.goal(label, { componentId: id, arm }, 1.0, 0);\n },\n fireStep: (name, weight, stepIndex) => {\n client.componentGoal(id, name, { reward: weight });\n client.goal(name, { componentId: id, arm }, weight, stepIndex);\n },\n });\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [client, id, goalKey, arm, source]);\n\n const props = useMemo(() => {\n const p: Record<string, string> = { 'data-sentient-slot': id };\n for (const [dim, value] of Object.entries(tokens)) p[`data-${dim}`] = value;\n return p;\n }, [id, tokens]);\n\n return { tokens, props };\n}\n","import { useEffect, useReducer, useState, useSyncExternalStore } from 'react';\nimport { armOfResult, baselineResultFor, type SlotDeclInput, type SlotResult } from '@sentientui/core';\nimport { confidenceBand } from '@sentientui/policy';\nimport { useInitialPersona, useInitialSlots, useSentient } from './provider.js';\nimport { subscribeOverridesChanged, getOverridesVersion } from './override-events.js';\nimport { isDevBuild } from './adaptive-shared.js';\n\n// Warn once per slot id per page lifetime, not per render.\nconst warnedBaselineSlots = new Set<string>();\n\ndeclare global {\n interface Window {\n /** Test/devtools forcing: slot id → forced result (applyScenario sets this). */\n __sentient_slot_overrides?: Record<string, SlotResult>;\n /** Test/devtools forcing: forced persona (applyScenario sets this). */\n __sentient_persona_override?: { persona: string; confidence?: number };\n }\n}\n\nexport type SlotResolution = {\n result: SlotResult;\n /** Canonical arm string (`dim=value|…` for dims slots, arm id for arms slots). */\n arm: string;\n source: 'override' | 'preloaded' | 'client' | 'baseline';\n};\n\n/**\n * Internal. Resolves what a slot serves this render, synchronously:\n * test/devtools override → SSR-preloaded result → core client state\n * (decide cache, snapshot seed, failure baseline) → declared baseline.\n * Purely read-side: exposure/goal wiring belongs to the calling hook.\n */\nexport function useSlotResult(slotId: string, decl: SlotDeclInput): SlotResolution {\n // Re-render when devtools writes window.__sentient_slot_overrides.\n useSyncExternalStore(subscribeOverridesChanged, getOverridesVersion, () => 0);\n const client = useSentient();\n const initialSlots = useInitialSlots();\n const [, bump] = useReducer((n: number) => n + 1, 0);\n\n const override =\n typeof window !== 'undefined' ? window.__sentient_slot_overrides?.[slotId] : undefined;\n const preloaded = override === undefined ? initialSlots[slotId] : undefined;\n const fromClient =\n override === undefined && preloaded === undefined && client\n ? client.getSlotResult(slotId)\n : null;\n\n // Keyless local mode on a CSR-only page: nothing has decided this slot yet\n // (no SSR preload, no snapshot), so ask the local engine — zero network,\n // deterministic — and re-render when the decision lands. Keyed clients\n // never take this path: their slots decide server-side (SSR preload).\n const needsLocalDecide =\n client?.isLocal === true &&\n override === undefined &&\n preloaded === undefined &&\n fromClient === null;\n useEffect(() => {\n if (!needsLocalDecide || !client) return;\n let cancelled = false;\n void client.decide({ slots: [decl] }).then((outcome) => {\n if (!cancelled && outcome) bump();\n });\n return () => {\n cancelled = true;\n };\n // decl identity is fixed per slot id (callers memoize it on id).\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [client, slotId, needsLocalDecide]);\n\n const resolution: SlotResolution = (() => {\n if (override !== undefined) {\n return { result: override, arm: armOfResult(override), source: 'override' };\n }\n if (preloaded !== undefined) {\n return { result: preloaded, arm: armOfResult(preloaded), source: 'preloaded' };\n }\n if (fromClient !== null) {\n return { result: fromClient, arm: armOfResult(fromClient), source: 'client' };\n }\n const baseline = baselineResultFor(decl);\n return { result: baseline, arm: armOfResult(baseline), source: 'baseline' };\n })();\n\n // Dev-only: a live KEYED client that has settled on the declared baseline was\n // never decided — keyed clients decide slots server-side (SSR preload), and\n // (unlike local mode) issue no client-side decide, so this slot serves\n // baseline for the whole session and cannot learn. Callers gate exposure on\n // `source !== 'baseline'` so no phantom baseline impression is recorded; warn\n // once so the integrator preloads the decision. (Local mode's baseline is a\n // transient first paint before its decide resolves — excluded here.)\n useEffect(() => {\n if (!isDevBuild()) return;\n if (!client || client.isLocal === true) return;\n if (resolution.source !== 'baseline') return;\n if (warnedBaselineSlots.has(slotId)) return;\n warnedBaselineSlots.add(slotId);\n console.warn(\n `[sentient] slot \"${slotId}\" resolved to its baseline — no SSR-preloaded or decided result. ` +\n `Keyed clients decide slots server-side, so this slot serves baseline for the whole session ` +\n `and records no exposure. Preload it via loadAdaptiveDecision()/initialSlots so it can serve a decided arm and learn.`,\n );\n }, [client, resolution.source, slotId]);\n\n return resolution;\n}\n\n/**\n * Reads a forced persona: `window.__sentient_persona_override` (the devtools\n * panel, `applyScenario`, the Playwright/Cypress helpers) or the\n * `?sentient_persona=<PersonaKey>` URL param (mirrors `?sentient_variant=`).\n * Read POST-MOUNT only — it touches `window.location`.\n */\nfunction getPersonaOverride(): { persona: string; confidence: number } | null {\n if (typeof window === 'undefined') return null;\n const forced = window.__sentient_persona_override;\n if (forced?.persona) return { persona: forced.persona, confidence: forced.confidence ?? 1 };\n try {\n const value = new URLSearchParams(window.location.search).get('sentient_persona');\n if (value) return { persona: value, confidence: 1 };\n } catch {\n /* non-browser env */\n }\n return null;\n}\n\nexport type AdaptivePersona = {\n persona: string;\n confidence: number;\n band: 'low' | 'medium' | 'high';\n};\n\n/**\n * The current persona estimate for React consumers, resolved in priority\n * order: a forced override (devtools / `applyScenario` / `?sentient_persona=`)\n * → the SSR-provided `initialPersona` → the live client estimate (adopted\n * attributes / snapshot / decide). Returns `null` when nothing is known yet.\n *\n * Hydration-safe: the first render (server + pre-hydration client) uses ONLY\n * the SSR-provided persona so server and client agree; the override channel and\n * the live client estimate — neither visible to the server — are read after\n * mount. Re-renders when a persona/variant override is written, so devtools or\n * a test forcing a persona mid-session takes effect immediately.\n */\nexport function useAdaptivePersona(): AdaptivePersona | null {\n const client = useSentient();\n const initialPersona = useInitialPersona();\n // Re-render when the override channel is written. NOTE: unlike useAssignment /\n // AdaptiveText — which fold the override into the useSyncExternalStore snapshot\n // (getDevOverride returns a STABLE string) — persona can't: getPersonaOverride\n // allocates a fresh object each call, which would fail the snapshot's Object.is\n // check and trip React's \"getSnapshot should be cached\" loop guard. So we\n // subscribe to the stable version counter for reactivity and read the override\n // in the render body (behind a mounted gate). That one-frame post-mount flip is\n // harmless here because this hook is side-effect-free (no assign/exposure to\n // leak), which is exactly why useAssignment/AdaptiveText could NOT tolerate it.\n useSyncExternalStore(subscribeOverridesChanged, getOverridesVersion, () => 0);\n const [mounted, setMounted] = useState(false);\n useEffect(() => setMounted(true), []);\n\n const withBand = (p: { persona: string; confidence: number }): AdaptivePersona => ({\n persona: p.persona,\n confidence: p.confidence,\n band: confidenceBand(p.confidence),\n });\n\n // First render must match the server, which can see neither window nor the\n // client estimate — use only initialPersona to avoid a hydration mismatch on\n // a ?sentient_persona= page.\n if (!mounted) {\n return initialPersona ? withBand(initialPersona) : null;\n }\n const override = getPersonaOverride();\n if (override) return withBand(override);\n if (initialPersona) return withBand(initialPersona);\n const live = client ? client.getPersona() : null;\n return live ? withBand(live) : null;\n}\n","import { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport { attachMicroSignalDetectors, type ComponentGoalOptions } from '@sentientui/core';\nimport { useAdaptiveApiKey, useSentient } from './provider.js';\nimport { useAssignment } from './use-assignment.js';\nimport { registerComponent } from './devtools-registry.js';\nimport {\n attachGoalListeners,\n goalLabelOf,\n isDevBuild,\n normalizeGoal,\n trackExposure,\n type GoalConfig,\n} from './adaptive-shared.js';\n\nexport type UseAdaptiveBind = {\n ref: (el: HTMLElement | null) => void;\n 'data-sentient-id': string;\n 'data-sentient-variant': string;\n};\n\nexport type UseAdaptiveResult<T> = {\n variant: string;\n value: T;\n /** Spread on the rendered element — wires exposure, goal listeners, and micro-signals. */\n bind: UseAdaptiveBind;\n fireGoal: (goalType?: string, opts?: ComponentGoalOptions) => void;\n};\n\nconst warnedUnbound = new Set<string>();\n\n/**\n * Rung 2 — headless, measurement-complete variant swap. Supersedes\n * `useAssignment` (which selects a variant but wires no measurement).\n *\n * `goal` is REQUIRED: without one the optimizer accumulates exposures with\n * zero rewards and cannot learn. `bind` MUST be attached to the rendered\n * element — dev mode warns loudly when a slot renders unbound.\n *\n * ```tsx\n * const { value, bind } = useAdaptive('buy-box', {\n * variants: { calm: <CalmBuyBox/>, urgent: <UrgentBuyBox/> }, // first key = baseline\n * goal: 'buy_click',\n * });\n * return <div {...bind}>{value}</div>;\n * ```\n */\nexport function useAdaptive<T>(\n id: string,\n config: { variants: Record<string, T>; goal: string | GoalConfig },\n): UseAdaptiveResult<T> {\n if (isDevBuild() && !config.goal) {\n throw new Error(\n `[sentient] useAdaptive(\"${id}\"): a goal is required — without one the optimizer accumulates exposures with no rewards and cannot learn. Pass e.g. goal: 'buy_click'.`,\n );\n }\n\n const client = useSentient();\n const apiKey = useAdaptiveApiKey();\n // Freeze the variant-id array on the KEY SET (same convention as <Adaptive> /\n // AdaptiveGroup / useAdaptiveTokens): stable across renders for the same keys\n // yet updates if the declared set changes. Declared space is normally fixed\n // per slot id for a session.\n const variantKey = Object.keys(config.variants).join(' ');\n // eslint-disable-next-line react-hooks/exhaustive-deps\n const variantIds = useMemo(() => Object.keys(config.variants), [variantKey]);\n const { variantId, isOverride, settled } = useAssignment(id, variantIds);\n const variant = variantId ?? variantIds[0] ?? '';\n const value = config.variants[variant] as T;\n\n const [node, setNode] = useState<HTMLElement | null>(null);\n const nodeRef = useRef<HTMLElement | null>(null);\n const ref = useCallback((el: HTMLElement | null) => {\n nodeRef.current = el;\n setNode(el);\n }, []);\n\n const goalKey = typeof config.goal === 'string' ? config.goal : JSON.stringify(config.goal);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n const goal = useMemo(() => normalizeGoal(config.goal), [goalKey]);\n const goalLabel = goalLabelOf(config.goal);\n\n useEffect(() => registerComponent({ id, variantIds, goal: goalLabel }), [id, variantIds, goalLabel]);\n\n // Exposure — same variant_assigned mechanics as <Adaptive>, fired once per\n // (id, variant) once the bind target is in the DOM.\n const exposedRef = useRef<string | null>(null);\n useEffect(() => {\n // Forced variants are a dev/test view — no exposure, no goals, no\n // micro-signals may be recorded (same gate as <Adaptive>).\n if (isOverride) return;\n // Only the SETTLED assignment is a real exposure; the interim variantIds[0]\n // placeholder shown while assign() is in flight must not accrue a phantom\n // baseline impression (same gate as <Adaptive>).\n if (!settled) return;\n if (!client || !variant || !node) return;\n if (exposedRef.current === variant) return;\n exposedRef.current = variant;\n trackExposure(client, apiKey, id, variant);\n }, [client, apiKey, id, variant, node, isOverride, settled]);\n\n // Goal listeners — identical machinery to <Adaptive> (shared helper).\n const goalFiredRef = useRef(false);\n useEffect(() => {\n goalFiredRef.current = false;\n }, [variant, goalKey]);\n useEffect(() => {\n if (isOverride) return;\n if (!client || !variant || !node) return;\n return attachGoalListeners(node, goal, {\n fireGoal: () => {\n if (goalFiredRef.current) return;\n goalFiredRef.current = true;\n client.track({\n projectId: apiKey,\n componentId: id,\n variantId: variant,\n eventType: 'goal_achieved',\n goalType: goalLabel,\n payload: { reward: 1.0 },\n });\n client.goal(goalLabel, { componentId: id, variantId: variant }, 1.0, 0);\n },\n fireStep: (name, weight, stepIndex) => {\n client.track({\n projectId: apiKey,\n componentId: id,\n variantId: variant,\n eventType: 'goal_achieved',\n goalType: name,\n payload: { reward: weight },\n });\n client.goal(name, {}, weight, stepIndex);\n },\n });\n }, [client, node, variant, apiKey, id, goal, goalLabel, isOverride]);\n\n // Micro-signal detectors — the third thing <Adaptive>'s container wires.\n useEffect(() => {\n if (isOverride) return;\n if (!client || !variant || !node) return;\n const assignedAt = Date.now();\n return attachMicroSignalDetectors(\n (signalType, extra = {}) => {\n client.track({\n projectId: apiKey,\n componentId: id,\n variantId: variant,\n eventType: 'micro_signal',\n payload: { signalType, ...extra },\n });\n },\n node,\n assignedAt,\n );\n }, [client, node, variant, apiKey, id, isOverride]);\n\n // Dev warning: bind never attached shortly after mount → exposures would\n // never fire and the slot cannot learn. Once per slot id.\n useEffect(() => {\n if (!isDevBuild()) return;\n if (!client) return;\n const timer = setTimeout(() => {\n if (!nodeRef.current && !warnedUnbound.has(id)) {\n warnedUnbound.add(id);\n console.warn(\n `[sentient] useAdaptive(\"${id}\"): bind was never attached — spread {...bind} on the rendered element, otherwise exposure and goal tracking cannot work and the optimizer learns nothing.`,\n );\n }\n }, 0);\n return () => clearTimeout(timer);\n }, [client, id]);\n\n const fireGoal = useCallback(\n (goalType?: string, opts?: ComponentGoalOptions) => {\n if (isOverride) return; // forced variants record nothing, even manual goals\n // componentGoal credits the bandit; goal() writes the session goal-funnel\n // record. The declared-goal listener above fires both, so a manual goal\n // for the same slot must too (otherwise it's absent from the funnel).\n // Like useAdaptiveGoal, this writes one funnel record per call with no\n // cross-call latch — keep goal labels unique per conversion (a component\n // that ALSO fires a declared goal on the same action records both).\n const name = goalType ?? goalLabel;\n client?.componentGoal(id, name, opts);\n client?.goal(name, opts?.metadata ?? {}, opts?.reward ?? 1.0, 0);\n },\n [client, id, goalLabel, isOverride],\n );\n\n const bind = useMemo<UseAdaptiveBind>(\n () => ({ ref, 'data-sentient-id': id, 'data-sentient-variant': variant }),\n [ref, id, variant],\n );\n\n return { variant, value, bind, fireGoal };\n}\n","import { Children, isValidElement, useEffect, useMemo, useRef, type ReactNode } from 'react';\nimport type { SlotDeclInput } from '@sentientui/core';\nimport { useAdaptiveApiKey, useSentient } from './provider.js';\nimport { useSlotResult } from './use-slot-result.js';\nimport { registerSlot } from './devtools-registry.js';\nimport {\n attachGoalListeners,\n goalLabelOf,\n isDevBuild,\n normalizeGoal,\n trackExposure,\n type GoalConfig,\n} from './adaptive-shared.js';\n\nexport type AdaptiveGroupProps = {\n id: string;\n /** Arrangement id → ordered child keys. FIRST key = baseline default. */\n arrangements: Record<string, string[]>;\n /** Explicit baseline arrangement id (defaults to the first declared). */\n baseline?: string;\n /** Optional slot-scoped goal — credited via componentGoal(group id). */\n goal?: string | GoalConfig;\n /** Keyed children — every key referenced by an arrangement must exist. */\n children: ReactNode;\n};\n\n// Warn once per group id per page lifetime.\nconst warnedGroups = new Set<string>();\n\n/**\n * Rung 3 — bounded mini-layout. Reorders KEYED children into the decided\n * arrangement (enumerated-arms slot: arms = Object.keys(arrangements)).\n * Declared orders only — never free permutation, never show/hide.\n * Fail-safe: unknown arrangement or key mismatch renders declaration order.\n */\nexport function AdaptiveGroup(props: AdaptiveGroupProps): JSX.Element {\n const client = useSentient();\n const apiKey = useAdaptiveApiKey();\n const containerRef = useRef<HTMLDivElement>(null);\n\n // Freeze the arrangement-id array on the KEY SET (same convention as\n // <Adaptive> / useAdaptive / useAdaptiveTokens): stable across renders for the\n // same keys yet updates if the declared set changes. Declared space is\n // normally fixed per group id for a session.\n const arrangementKey = Object.keys(props.arrangements).join(' ');\n // eslint-disable-next-line react-hooks/exhaustive-deps\n const arrangementIds = useMemo(() => Object.keys(props.arrangements), [arrangementKey]);\n const decl = useMemo<SlotDeclInput>(\n () => ({\n id: props.id,\n arms: arrangementIds,\n ...(props.baseline !== undefined ? { baseline: props.baseline } : {}),\n }),\n [props.id, arrangementIds, props.baseline],\n );\n const { arm, source } = useSlotResult(props.id, decl);\n\n if (\n isDevBuild() &&\n props.baseline !== undefined &&\n props.baseline !== arrangementIds[0] &&\n !warnedGroups.has(props.id + ':baseline')\n ) {\n warnedGroups.add(props.id + ':baseline');\n console.warn(\n `[sentient] <AdaptiveGroup id=\"${props.id}\">: baseline \"${props.baseline}\" is not the first-declared arrangement (\"${arrangementIds[0]}\"). The first arrangement should usually be the page's real incumbent (the holdout sees it).`,\n );\n }\n\n const childArray = Children.toArray(props.children).filter(isValidElement);\n const byKey = new Map<string, (typeof childArray)[number]>();\n for (const child of childArray) {\n // Children.toArray prefixes explicit keys with '.$'.\n byKey.set(String(child.key ?? '').replace(/^\\.\\$/, ''), child);\n }\n\n const order = props.arrangements[arm];\n const canReorder =\n order !== undefined &&\n order.length === childArray.length &&\n order.every((key) => byKey.has(key));\n\n if (\n isDevBuild() &&\n order !== undefined &&\n !canReorder &&\n !warnedGroups.has(props.id + ':keys')\n ) {\n warnedGroups.add(props.id + ':keys');\n console.warn(\n `[sentient] <AdaptiveGroup id=\"${props.id}\">: arrangement \"${arm}\" [${order.join(', ')}] does not match the children's keys — rendering declaration order (fail-safe).`,\n );\n }\n\n const ordered = canReorder ? order.map((key) => byKey.get(key)!) : childArray;\n\n // Devtools slot registry — the declared arms space drives persona simulation\n // and the panel's per-arm override buttons. A group is a slot, not a component:\n // registering it as one produced buttons that wrote the wrong override channel.\n useEffect(\n () => registerSlot({ id: props.id, arms: Object.keys(props.arrangements) }),\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [props.id],\n );\n\n // Exposure — once per (group, arrangement). An unresolved `baseline` source\n // means the group was never decided (interim local decide, or a keyed client\n // with no SSR preload); exposing it would record a phantom baseline\n // impression that can never convert, so skip until a real arm resolves.\n const exposedArmRef = useRef<string | null>(null);\n useEffect(() => {\n // A forced arm (`override`, from devtools/tests) is a preview, not a real\n // exposure — skip it so the optimizer isn't trained on the override (same\n // contract <Adaptive> honors for component overrides).\n if (!client || source === 'baseline' || source === 'override' || exposedArmRef.current === arm) return;\n exposedArmRef.current = arm;\n trackExposure(client, apiKey, props.id, arm);\n }, [client, apiKey, props.id, arm, source]);\n\n // Optional goal — slot-scoped credit through componentGoal (the core\n // resolves the attributed arm from its slot state; see Task 3.3).\n const goalKey =\n props.goal === undefined ? null : typeof props.goal === 'string' ? props.goal : JSON.stringify(props.goal);\n useEffect(() => {\n // Forced arms record nothing (preview only) — same gate as the exposure.\n if (!client || props.goal === undefined || source === 'override') return;\n const node = containerRef.current;\n if (!node) return;\n const label = goalLabelOf(props.goal);\n let fired = false;\n return attachGoalListeners(node, normalizeGoal(props.goal), {\n fireGoal: () => {\n if (fired) return;\n fired = true;\n // componentGoal credits the bandit; goal() writes the session-level\n // conversion funnel record — matching <Adaptive>. Firing only the\n // former left group conversions out of the goal funnel.\n client.componentGoal(props.id, label);\n client.goal(label, { componentId: props.id, arm }, 1.0, 0);\n },\n fireStep: (name, weight, stepIndex) => {\n client.componentGoal(props.id, name, { reward: weight });\n client.goal(name, { componentId: props.id, arm }, weight, stepIndex);\n },\n });\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [client, props.id, goalKey, arm, source]);\n\n return (\n <div ref={containerRef} data-sentient-id={props.id} data-sentient-variant={arm}>\n {ordered}\n </div>\n );\n}\n","/** @deprecated Use `useSessionSegment()` from the provider, or `deriveSessionSegment` from `@sentientui/core`. */\nexport { deriveSessionSegment as detectSegment } from '@sentientui/core';\n","/**\n * Agent-readable content feed. Merges SDK-known data (winning variants, layout\n * order) with developer-supplied page content, and renders it either as a\n * server-rendered inline JSON-LD block (read by passive AI crawlers, which do\n * not run JS) or as Markdown (for agents that content-negotiate `text/markdown`).\n *\n * No React or DOM APIs — safe to import in server components, route handlers,\n * and middleware.\n */\n\nexport type AgentBlock = {\n /** Component ID. */\n id: string;\n /** Winning variant ID currently served. */\n variant: string;\n /** Agent-readable data attached to the served variant, if any. */\n content?: unknown;\n};\n\nexport type AgentFeed = {\n page: string;\n title?: string;\n summary?: string;\n layoutOrder?: string[];\n blocks: AgentBlock[];\n /** Developer-supplied extra fields (products, specs, arbitrary JSON). */\n [key: string]: unknown;\n};\n\n/** Fields the SDK owns — developer content can never overwrite these. */\nconst RESERVED_FIELDS = ['page', 'blocks', 'layoutOrder'] as const;\n\nconst registry = new Map<string, Record<string, unknown>>();\n\n/**\n * Register page-level structured content the SDK can't infer (title, summary,\n * product fields, arbitrary JSON), keyed by page path. Call at module load.\n */\nexport function defineAgentContent(page: string, content: Record<string, unknown>): void {\n registry.set(page, content);\n}\n\n/** Look up registered content for a page. */\nexport function getAgentContent(page: string): Record<string, unknown> | undefined {\n return registry.get(page);\n}\n\n/** Clear the registry — intended for tests. */\nexport function clearAgentContent(): void {\n registry.clear();\n}\n\n/**\n * Merge SDK-known data with developer-supplied content into a single feed.\n * Developer content fills in title/summary/etc. but can never overwrite the\n * SDK-authoritative fields (`page`, `blocks`, `layoutOrder`).\n */\nexport function buildAgentFeed(input: {\n page: string;\n blocks: AgentBlock[];\n layoutOrder?: string[];\n content?: Record<string, unknown>;\n}): AgentFeed {\n const supplied = input.content ?? getAgentContent(input.page) ?? {};\n const safe: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(supplied)) {\n if (!(RESERVED_FIELDS as readonly string[]).includes(k)) safe[k] = v;\n }\n const feed: AgentFeed = {\n ...safe,\n page: input.page,\n blocks: input.blocks,\n };\n if (input.layoutOrder) feed.layoutOrder = input.layoutOrder;\n return feed;\n}\n\n/**\n * Render the feed as a server-rendered inline JSON-LD `<script>` string. `<` is\n * escaped to `<` so embedded content cannot break out of the script\n * element. MUST be emitted on the server — passive crawlers never run client JS.\n */\nexport function renderAgentJsonLd(feed: AgentFeed): string {\n return `<script type=\"application/ld+json\">${renderAgentJsonLdBody(feed)}</script>`;\n}\n\n/**\n * The escaped JSON-LD body only (no `<script>` wrapper). For React server\n * components, inject via `<script type=\"application/ld+json\"\n * dangerouslySetInnerHTML={{ __html: renderAgentJsonLdBody(feed) }} />`.\n */\nexport function renderAgentJsonLdBody(feed: AgentFeed): string {\n return JSON.stringify({ '@context': 'https://schema.org', '@type': 'WebPage', ...feed })\n .replace(/</g, '\\\\u003c');\n}\n\n/** Render the feed as Markdown for agents that negotiate `text/markdown`. */\nexport function renderAgentMarkdown(feed: AgentFeed): string {\n const lines: string[] = [];\n if (feed.title) lines.push(`# ${feed.title}`, '');\n if (feed.summary) lines.push(String(feed.summary), '');\n\n for (const [k, v] of Object.entries(feed)) {\n if (['page', 'title', 'summary', 'blocks', 'layoutOrder'].includes(k)) continue;\n lines.push(`## ${k}`, '', '```json', JSON.stringify(v, null, 2), '```', '');\n }\n\n if (feed.blocks.length > 0) {\n lines.push('## blocks', '');\n for (const b of feed.blocks) {\n lines.push(`- **${b.id}** → variant \\`${b.variant}\\``);\n if (b.content !== undefined) {\n lines.push('', ' ```json', JSON.stringify(b.content, null, 2), ' ```');\n }\n }\n lines.push('');\n }\n\n return lines.join('\\n').trimEnd() + '\\n';\n}\n"],"mappings":"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","names":["src_exports","__export","Adaptive","AdaptiveGroup","AdaptiveProvider","AdaptiveText","SentientPersonaScript","buildAgentFeed","defineAgentContent","getAgentContent","renderAgentJsonLd","renderAgentJsonLdBody","renderAgentMarkdown","useAdaptive","useAdaptiveApiBaseUrl","useAdaptiveGoal","useAdaptivePersona","useAdaptiveTokens","useAssignment","useInitialAssignments","useLayoutOrder","useSentient","__toCommonJS","import_react","import_core","store","listeners","subscribe","componentId","cb","set","update","weights","e","getWeights","_a","ssrFallback","state","w","getPreviewMode","state","subscribePreview","fn","listeners","createPreviewClient","inner","componentId","segment","variantIds","agentData","agentDataByVariant","slotId","EVENT","getOverridesVersion","_a","subscribeOverridesChanged","fn","EVENT","publishDevtoolsConfig","config","isDevBuild","_a","normalizeGoal","goal","goalLabelOf","isClickableTarget","el","tag","findClickable","start","container","selector","cursor","e","attachGoalListeners","node","handlers","firedSteps","wcCleanups","sub","stepName","stepWeight","idx","fireStep","onClick","target","onSubmit","threshold","io","entries","entry","c","subgoals","remaining","_","i","checkComposite","cleanups","trackExposure","client","apiKey","componentId","variantId","ssrFallback","state","w","emit","fn","NOOP_UNREGISTER","registerComponent","c","isDevBuild","registerSlot","s","registerSections","sections","import_jsx_runtime","deriveDefaultSegment","_a","_b","device","source","e","DEFAULT_API_BASE_URL","AdaptiveContext","useConsentSource","granted","setGranted","sourceRef","cookie","value","event","hasCheck","read","s","want","c","onDecision","AdaptiveProvider","props","client","setClient","sessionSegment","previewOn","setPreviewOn","getPreviewMode","subscribePreview","sourceGranted","consent","prev","config","cancelled","created","stopEngagement","startEngagement","startEngagementCapture","initGraph","__spreadProps","__spreadValues","poll","entries","entry","weights","v","update","timerId","ssrFallback","apiBaseUrl","frozenConfigRef","current","key","publishDevtoolsConfig","registerSections","exposedClient","createPreviewClient","_c","_d","_e","useSentient","useAdaptiveApiKey","useInitialAssignments","useSessionSegment","useSsrFallback","useOnAssignment","useDebug","useLayoutOrder","contextOrder","override","subscribeOverridesChanged","useInitialSlots","useInitialPersona","useAdaptiveApiBaseUrl","import_react","import_core","import_react","getDevOverride","componentId","_a","global","params","raw","sep","e","PRIOR_PULLS","pickFromWeights","weights","variantIds","_a","_b","best","v","pulls","score","useAssignment","componentId","agentData","agentDataByVariant","initialAssignments","useInitialAssignments","ssrFallback","useSsrFallback","client","useSentient","segment","useSessionSegment","onAssignment","useOnAssignment","debug","useDebug","assignmentReportedRef","devOverride","subscribeOverridesChanged","getDevOverride","overrideVariant","overrideLoggedRef","state","setState","preloaded","cached","getWeights","chosen","reportAssignment","variantId","prev","cancelled","result","subscribe","import_jsx_runtime","AdaptiveImpl","props","_a","client","useSentient","apiKey","useAdaptiveApiKey","variantKey","variantIds","variantId","content","isOverride","settled","useAssignment","containerRef","mounted","setMounted","goalFiredRef","microGoalFiredRef","assignTrackedRef","goalKey","goal","normalizeGoal","goalLabel","registerComponent","trackExposure","node","timerId","hoverStart","onEnter","onLeave","assignedAt","signalType","extra","_b","_c","__spreadValues","mapping","name","weight","stepIndex","attachGoalListeners","jsxContent","managedContent","isDevBuild","Adaptive","prev","next","prevKeys","nextKeys","k","import_react","import_jsx_runtime","AdaptiveText","id","defaultText","Tag","className","goalProp","_a","client","useSentient","apiKey","useAdaptiveApiKey","onAssignment","useOnAssignment","segment","useSessionSegment","trackedRef","nodeRef","override","subscribeOverridesChanged","getDevOverride","text","setText","_b","variantId","setVariantId","cancelled","result","isDevBuild","goalKey","goal","normalizeGoal","goalLabel","goalFiredRef","node","attachGoalListeners","name","weight","stepIndex","displayText","cached","el","import_react","useAdaptiveGoal","componentId","client","useSentient","goalType","opts","_a","_b","getDevOverride","import_core","import_policy","import_jsx_runtime","inlineJsString","value","personaScriptBody","props","SentientPersonaScript","import_react","import_policy","import_react","import_core","import_policy","warnedBaselineSlots","useSlotResult","slotId","decl","_a","subscribeOverridesChanged","getOverridesVersion","client","useSentient","initialSlots","useInitialSlots","bump","n","override","preloaded","fromClient","needsLocalDecide","cancelled","outcome","resolution","baseline","isDevBuild","getPersonaOverride","forced","value","e","useAdaptivePersona","initialPersona","useInitialPersona","mounted","setMounted","withBand","p","live","warnedTokenSlots","cssEscape","value","useAdaptiveTokens","id","dims","opts","client","useSentient","apiKey","useAdaptiveApiKey","dimsKey","decl","result","arm","source","useSlotResult","tokens","isDevBuild","validity","k","v","space","n","values","goalKey","registerSlot","exposedArmRef","trackExposure","node","label","goalLabelOf","fired","attachGoalListeners","normalizeGoal","name","weight","stepIndex","props","p","dim","import_react","import_core","warnedUnbound","useAdaptive","id","config","_a","isDevBuild","client","useSentient","apiKey","useAdaptiveApiKey","variantKey","variantIds","variantId","isOverride","settled","useAssignment","variant","value","node","setNode","nodeRef","ref","el","goalKey","goal","normalizeGoal","goalLabel","goalLabelOf","registerComponent","exposedRef","trackExposure","goalFiredRef","attachGoalListeners","name","weight","stepIndex","assignedAt","signalType","extra","__spreadValues","timer","fireGoal","goalType","opts","_b","bind","import_react","import_jsx_runtime","warnedGroups","AdaptiveGroup","props","_a","client","useSentient","apiKey","useAdaptiveApiKey","containerRef","arrangementKey","arrangementIds","decl","__spreadValues","arm","source","useSlotResult","isDevBuild","childArray","byKey","child","order","canReorder","key","ordered","registerSlot","exposedArmRef","trackExposure","goalKey","node","label","goalLabelOf","fired","attachGoalListeners","normalizeGoal","name","weight","stepIndex","import_core","RESERVED_FIELDS","registry","defineAgentContent","page","content","getAgentContent","buildAgentFeed","input","_a","_b","supplied","getAgentContent","safe","k","v","RESERVED_FIELDS","feed","__spreadProps","__spreadValues","renderAgentJsonLd","renderAgentJsonLdBody","renderAgentMarkdown","lines","b","import_core"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/provider.tsx","../src/weights-store.ts","../src/preview-mode.ts","../src/override-events.ts","../src/devtools-config.ts","../src/adaptive-shared.ts","../src/devtools-registry.ts","../src/adaptive.tsx","../src/use-assignment.ts","../src/dev-override.ts","../src/adaptive-text.tsx","../src/use-adaptive-goal.ts","../src/use-page-goal.ts","../src/persona-script.tsx","../src/use-adaptive-tokens.ts","../src/use-slot-result.ts","../src/use-adaptive.ts","../src/adaptive-group.tsx","../src/segment.ts","../src/agent-feed.ts"],"sourcesContent":["export { AdaptiveProvider, useSentient, useInitialAssignments, useLayoutOrder, useAdaptiveApiBaseUrl } from './provider.js';\nexport type { AdaptiveProviderProps, SsrFallback } from './provider.js';\n\nexport { Adaptive } from './adaptive.js';\nexport type {\n AdaptiveProps,\n GoalConfig,\n ClickGoal,\n ScrollDepthGoal,\n FormSubmitGoal,\n CompositeGoal,\n WeightedStep,\n WeightedCompositeGoal,\n MicroSignalGoals,\n MicroSignalGoalConfig,\n} from './adaptive.js';\n\nexport { AdaptiveText } from './adaptive-text.js';\nexport type { AdaptiveTextProps } from './adaptive-text.js';\n\n/**\n * @deprecated Use {@link useAdaptive} instead — it selects a variant AND wires\n * exposure, goal, and micro-signal tracking. `useAssignment` only selects, so a\n * component built on it directly records no learning signal. Kept exported for\n * back-compat (it is `useAdaptive`'s internal selection engine); moving to\n * internal-only in 1.0.0.\n */\nexport { useAssignment } from './use-assignment.js';\nexport type { AssignmentState } from './use-assignment.js';\n\nexport { useAdaptiveGoal } from './use-adaptive-goal.js';\nexport type { FireGoal } from './use-adaptive-goal.js';\n\nexport { usePageGoal } from './use-page-goal.js';\nexport type { PageGoalOptions } from './use-page-goal.js';\n\nexport { SentientPersonaScript } from './persona-script.js';\nexport type { SentientPersonaScriptProps } from './persona-script.js';\n\nexport { useAdaptiveTokens } from './use-adaptive-tokens.js';\nexport type { UseAdaptiveTokensOptions, UseAdaptiveTokensResult } from './use-adaptive-tokens.js';\n\nexport { useAdaptive } from './use-adaptive.js';\nexport type { UseAdaptiveResult, UseAdaptiveBind } from './use-adaptive.js';\n\nexport { useAdaptivePersona } from './use-slot-result.js';\nexport type { AdaptivePersona } from './use-slot-result.js';\n\nexport { AdaptiveGroup } from './adaptive-group.js';\nexport type { AdaptiveGroupProps } from './adaptive-group.js';\n\nexport type { ComponentWeights, VariantWeight } from './weights-store.js';\n\nexport { detectSegment } from './segment.js';\n\nexport {\n defineAgentContent,\n getAgentContent,\n buildAgentFeed,\n renderAgentJsonLd,\n renderAgentJsonLdBody,\n renderAgentMarkdown,\n} from './agent-feed.js';\nexport type { AgentFeed, AgentBlock } from './agent-feed.js';\n\n// Re-exported from core so a React app can wire its consent banner to the SDK\n// without adding @sentientui/core as a direct dependency — the docs already\n// point React users at grantConsent(), so it belongs on this entry.\n//\n// Safe here, unlike the server-only helpers re-exported from /next: this index\n// carries no 'use client' directive, and grantConsent is browser-only (it\n// returns immediately during SSR), so it is only ever called from a client\n// component and never becomes a client reference invoked on the server.\nexport { grantConsent } from '@sentientui/core';\n","'use client';\n\ndeclare const process: { env?: { NODE_ENV?: string } } | undefined;\n\nimport {\n createContext,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState,\n useSyncExternalStore,\n type ReactNode,\n} from 'react';\nimport {\n detectDeviceClass,\n detectTrafficSource,\n init,\n type SentientClient,\n type SentientConfig,\n type SlotResult,\n} from '@sentientui/core';\nimport { update as updateWeightsStore, type ComponentWeights } from './weights-store.js';\nimport { getPreviewMode, subscribePreview, createPreviewClient } from './preview-mode.js';\nimport { subscribeOverridesChanged } from './override-events.js';\nimport { publishDevtoolsConfig } from './devtools-config.js';\nimport { registerSections } from './devtools-registry.js';\n\n/**\n * Mirrors the segment derivation inside core `init()` so the cache key used\n * by `useAssignment` always matches the key `assign()` writes under. Before\n * this, the context defaulted to 'desktop:direct' while core used the\n * detected segment — a systematic cache miss for every integration that\n * didn't pass `sessionSegment` explicitly.\n */\nfunction deriveDefaultSegment(): string {\n if (typeof window === 'undefined') return 'desktop:direct';\n try {\n const device = detectDeviceClass(navigator.userAgent ?? '');\n const source = detectTrafficSource(document.referrer ?? '', window.location.origin);\n return `${device}:${source}`;\n } catch {\n return 'desktop:direct';\n }\n}\n\nconst DEFAULT_API_BASE_URL = 'https://api.sentient-ui.com/v1';\n\n/** How to render adaptive slots during SSR when assignments are not preloaded. */\nexport type SsrFallback = 'first' | 'none';\n\ntype AdaptiveContextValue = {\n client: SentientClient | null;\n // The publishable API key (pk_…). Historically named `projectId` because the\n // API uses it as the project identifier on the wire, but it is the API key,\n // not the project UUID. Field renamed for clarity.\n apiKey: string;\n initialAssignments: Record<string, string>;\n sessionSegment: string;\n ssrFallback: SsrFallback;\n onAssignment: ((componentId: string, variantId: string) => void) | undefined;\n initialLayoutOrder: string[] | null;\n initialSlots: Record<string, SlotResult>;\n initialPersona: { persona: string; confidence: number } | null;\n apiBaseUrl: string;\n debug: boolean;\n};\n\nconst AdaptiveContext = createContext<AdaptiveContextValue>({\n client: null,\n apiKey: '',\n initialAssignments: {},\n sessionSegment: 'desktop:direct',\n ssrFallback: 'first',\n onAssignment: undefined,\n initialLayoutOrder: null,\n initialSlots: {},\n initialPersona: null,\n apiBaseUrl: DEFAULT_API_BASE_URL,\n debug: false,\n});\n\nexport type AdaptiveProviderProps = {\n apiKey: string;\n context: SentientConfig['context'];\n debug?: boolean;\n /**\n * SSR-preloaded assignments from `preloadAssignments()` / `loadAdaptiveAssignments()`.\n * Passed through to `useAssignment` as synchronous initial state so crawlers and\n * the first paint see real content (recommended for SEO).\n */\n initialAssignments?: Record<string, string>;\n /**\n * Bandit segment from SSR (`device:source`). Keeps cache, assign, and worker\n * weights on one row — must match `loadAdaptiveAssignments` / session upsert.\n */\n sessionSegment?: string;\n /**\n * When no `initialAssignments` exist for a component, `'first'` renders\n * `variantIds[0]` in server HTML (safe default for SEO). Use `'none'` only for\n * decorative slots marked `clientOnly`.\n * @default 'first'\n */\n ssrFallback?: SsrFallback;\n /**\n * Consent gate. When `false` the SDK is not initialised and no events are\n * sent. Flip to `true` (e.g. after the user accepts the cookie banner) to\n * initialise and begin tracking.\n */\n consent?: boolean;\n /**\n * Where to read the visitor's consent decision from, so the SDK can gate and\n * un-gate itself instead of the host app wiring `grantConsent()` by hand.\n *\n * Keep your own banner or CMP — this only tells us how to observe it. The\n * provider reads the source on mount, re-reads it whenever `event` fires, and\n * initialises the moment it grants. Nothing is requested and no cookie is set\n * until then, and there is no page reload.\n *\n * Because the provider owns the whole lifecycle there is no ordering rule to\n * get right: pass this instead of managing `consent` yourself.\n *\n * @example // cookie written by your own banner\n * consentFrom={{ cookie: 'cookie_consent', value: 'accepted', event: 'consent-decided' }}\n * @example // a CMP that exposes an object rather than a cookie\n * consentFrom={{ check: () => window.Cookiebot?.consent?.statistics === true,\n * event: 'CookiebotOnAccept' }}\n */\n consentFrom?: {\n /** Cookie to read. Granted when its value equals `value`. */\n cookie?: string;\n /** Cookie value that means granted. @default 'accepted' */\n value?: string;\n /** Predicate for CMPs with a JS API. Takes precedence over `cookie`. */\n check?: () => boolean;\n /**\n * `window` event that signals a decision. The source is re-read when it\n * fires — the event's payload is never trusted — so any CMP's event works.\n */\n event?: string;\n };\n /**\n * Behavior before consent is granted. Pass `'statistical_winner'` to serve the\n * best-performing variant via `GET /v1/winner` with zero tracking while the\n * consent banner is showing. Requires `consent: false`.\n * @see SentientConfig.preConsentBehavior\n */\n preConsentBehavior?: 'statistical_winner' | 'control';\n /**\n * Honor the browser's Do Not Track signal. Defaults to `true`: when DNT is\n * enabled the SDK sets no cookies and sends no tracking data (overriding\n * `consent: true`). Set `false` to make your own consent gate authoritative.\n * @see SentientConfig.respectDoNotTrack\n */\n respectDoNotTrack?: boolean;\n /**\n * Called once per component the first time a variant is resolved for that\n * component in this session. Use to forward assignments to your own analytics\n * (Mixpanel, PostHog, Segment, etc.) without having to wrap `useAssignment`.\n */\n onAssignment?: (componentId: string, variantId: string) => void;\n /**\n * SSR-preloaded section order from `loadAdaptiveDecision()`.\n * Pass the `layoutOrder` field from `DecideResult`. When set,\n * `useLayoutOrder()` returns this on first render so there is no layout shift.\n */\n initialLayoutOrder?: string[] | null;\n /**\n * The section ids the app declares as reorderable, independent of any\n * decision. `AdaptiveRoot` forwards its `sections` prop here.\n *\n * Devtools reads this to offer layout previewing: a page whose decision was\n * gated by consent, or timed out, has no `initialLayoutOrder`, and registering\n * only that left the layout panel empty in exactly the situation you reach for\n * it — running the site locally before accepting a cookie banner.\n */\n declaredSections?: string[];\n /**\n * SSR-preloaded slot results from `loadAdaptiveDecision()` (the `slots`\n * field of its result). Guarantees `useAdaptiveTokens`/`AdaptiveGroup`\n * render the decided arm in server HTML — zero flicker, hydration-safe.\n */\n initialSlots?: Record<string, SlotResult>;\n /**\n * Persona decided during SSR (`persona` + `confidence` fields of\n * `loadAdaptiveDecision()`'s result). Adopted by the core client;\n * rendered into html attributes only by `SentientPersonaScript`.\n */\n initialPersona?: { persona: string; confidence: number };\n /**\n * Base URL of the Sentient API (no trailing slash). Read by the devtools\n * panel for /v1/explain and by future client helpers. Defaults to the\n * hosted API.\n */\n apiBaseUrl?: string;\n /**\n * Session ID generated during SSR (the `sessionId` field returned by\n * `loadAdaptiveAssignments` / `loadAdaptiveDecision`). When provided and no\n * existing session cookie or localStorage entry is found, the client adopts\n * this ID so events and goals are attributed to the same session the server\n * used for variant assignment.\n */\n ssrSessionId?: string;\n /**\n * ISO 3166-1 alpha-2 country code. Pass the value of the `CF-IPCountry`\n * header from your Next.js server component to populate country on landing\n * sessions without client-side geo lookup.\n */\n country?: string;\n /**\n * Keyless local mode. 'auto' (default) simulates decisions on-device in\n * development builds when no valid API key is configured; `true` forces the\n * local engine; `false` restores the silent keyless no-op.\n * @see SentientConfig.localMode\n */\n localMode?: 'auto' | boolean;\n /**\n * DOM graph scanning + page-structure sync. ON by default: the provider\n * dynamically loads `@sentientui/core/graph` and uses its graph-capable\n * `init()` for the single client, so the SDK scans your page structure,\n * auto-detects semantic sections, and syncs them to power personas and the\n * dashboard graph page. Pass `false` to keep the lean bundle only.\n */\n enableGraph?: boolean;\n /**\n * Include captured heading / DOM text in graph sync payloads. OFF by default.\n * Only applies when graph scanning is enabled (`enableGraph` not `false`).\n */\n captureDomText?: boolean;\n /**\n * Behavioral engagement capture (per-section dwell/scroll + semantic section\n * registration) powering personas. ON by default — pass `false` to disable.\n * Never runs for a DNT/GPC or consent-gated visitor (no client → no capture).\n */\n engagement?: boolean;\n children: ReactNode;\n};\n\n/**\n * Watches a {@link AdaptiveProviderProps.consentFrom} source and reports whether\n * it currently grants consent. Returns false (and subscribes to nothing) when no\n * source is configured.\n */\nfunction useConsentSource(source: AdaptiveProviderProps['consentFrom']): boolean {\n const [granted, setGranted] = useState(false);\n\n // The source is usually an inline object literal, so its identity changes\n // every render. Read it through a ref and key the effect on its primitives,\n // otherwise the listener would be torn down and re-added on every render.\n const sourceRef = useRef(source);\n sourceRef.current = source;\n\n const { cookie, value, event } = source ?? {};\n const hasCheck = typeof source?.check === 'function';\n\n useEffect(() => {\n const read = (): boolean => {\n const s = sourceRef.current;\n if (!s) return false;\n if (s.check) return s.check() === true;\n if (!s.cookie || typeof document === 'undefined') return false;\n const want = `${s.cookie}=${s.value ?? 'accepted'}`;\n return document.cookie.split('; ').some((c) => c.trim() === want);\n };\n\n if (read()) {\n setGranted(true);\n return;\n }\n if (!event) return;\n\n // Re-read rather than trusting the event payload, so this works with any\n // CMP's event shape (CookiebotOnAccept, OneTrustGroupsUpdated, …) and a\n // \"declined\" decision correctly leaves us gated.\n const onDecision = (): void => {\n if (read()) setGranted(true);\n };\n window.addEventListener(event, onDecision);\n return () => window.removeEventListener(event, onDecision);\n }, [cookie, value, event, hasCheck]);\n\n return granted;\n}\n\n/**\n * Initialises the Sentient core SDK in a useEffect (SSR-safe) and exposes the\n * client via React context. Re-initialises when consent changes.\n */\nexport function AdaptiveProvider(props: AdaptiveProviderProps): JSX.Element {\n const [client, setClient] = useState<SentientClient | null>(null);\n // Derived once per mount: identical to what core init() computes, so cache\n // reads (context segment) and cache writes (core segment) always agree.\n const [sessionSegment] = useState(() => props.sessionSegment ?? deriveDefaultSegment());\n // Devtools preview: when on, expose an event-suppressing client so previewing\n // variants/personas writes nothing. Off by default (inert in production).\n const [previewOn, setPreviewOn] = useState(getPreviewMode());\n useEffect(() => subscribePreview(() => setPreviewOn(getPreviewMode())), []);\n\n // When a consentFrom source is configured it owns the gate: start closed and\n // open only once the source grants. An explicit consent={true} (e.g. resolved\n // from the cookie on the server by AdaptiveRoot) short-circuits it, so a\n // returning visitor isn't gated waiting for a client-side re-read.\n const sourceGranted = useConsentSource(props.consentFrom);\n const consent = props.consentFrom ? props.consent === true || sourceGranted : props.consent;\n\n useEffect(() => {\n // When consent is explicitly false with no preConsentBehavior, tear down any existing client.\n if (consent === false && !props.preConsentBehavior) {\n setClient((prev: SentientClient | null) => {\n prev?.destroy();\n return null;\n });\n return;\n }\n\n const config = {\n apiKey: props.apiKey,\n context: props.context,\n debug: props.debug,\n initialAssignments: props.initialAssignments,\n sessionSegment,\n consent,\n preConsentBehavior: props.preConsentBehavior,\n respectDoNotTrack: props.respectDoNotTrack,\n ssrSessionId: props.ssrSessionId,\n country: props.country,\n localMode: props.localMode,\n initialSlots: props.initialSlots,\n initialPersona: props.initialPersona,\n ingestUrl: props.apiBaseUrl ? `${props.apiBaseUrl.replace(/\\/$/, '')}/events` : undefined,\n };\n\n // Track the client created by this effect run so cleanup destroys exactly\n // the right one, and so a late-resolving dynamic import can bail if the\n // effect was already torn down (unmount / consent change).\n let cancelled = false;\n let created: SentientClient | null = null;\n let stopEngagement: (() => void) | null = null;\n\n // Engagement capture (default ON): per-section dwell/scroll + semantic\n // section registration, lazy-loaded so the lean bundle stays lean. Only\n // ever started for an initialised client, so consent/DNT gates are\n // inherited (and the capture module re-checks DNT internally).\n const startEngagement = (c: SentientClient): void => {\n if (props.engagement === false) return;\n void import('@sentientui/core/engagement').then(({ startEngagementCapture }) => {\n if (cancelled) return;\n stopEngagement = startEngagementCapture(c, {\n apiKey: props.apiKey,\n apiBase: props.apiBaseUrl ? props.apiBaseUrl.replace(/\\/$/, '') : undefined,\n });\n });\n };\n\n if (props.enableGraph !== false) {\n // Graph scanning is the default — load the graph entry dynamically so the\n // scanner never lands in the lean bundle. The provider still creates ONE\n // client (graph-capable). Pass enableGraph={false} for the lean client.\n void import('@sentientui/core/graph').then(({ init: initGraph }) => {\n if (cancelled) return;\n created = initGraph({ ...config, graph: true, captureDomText: props.captureDomText === true });\n setClient(created);\n startEngagement(created);\n });\n } else {\n created = init(config);\n setClient(created);\n startEngagement(created);\n }\n\n return () => {\n cancelled = true;\n stopEngagement?.();\n // dispose, not destroy: effect cleanup runs on unmount, StrictMode's\n // dev double-invoke, and consent re-init — the visitor identity must\n // survive all of those. Full destroy() happens only on the explicit\n // consent-revocation branch above.\n created?.dispose();\n };\n // Re-init when consent changes — whether that came from the prop or from a\n // consentFrom source granting. Other props (incl. enableGraph) are\n // intentionally stable for a session.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [consent]);\n\n // Poll /v1/weights every 60 s so long-lived sessions see updated bandit weights\n // without a page reload. useAssignment subscribers react via weights-store.\n useEffect(() => {\n if (!client) return;\n let cancelled = false;\n const poll = async (): Promise<void> => {\n if (cancelled) return;\n let entries;\n try {\n entries = await client.fetchWeights();\n } catch {\n // Network/transient error: skip this cycle and retry on the next\n // interval. Swallowed deliberately so a failed poll never surfaces as\n // an unhandled rejection.\n return;\n }\n if (cancelled) return;\n for (const entry of entries) {\n const weights: ComponentWeights = {\n componentId: entry.componentId,\n updatedAt: entry.updatedAt,\n variants: entry.variants.map((v) => ({\n variantId: v.variantId,\n pulls: v.pulls,\n avgReward: v.avgReward ?? 0,\n })),\n };\n updateWeightsStore(entry.componentId, weights);\n }\n };\n void poll();\n const timerId = setInterval(() => void poll(), 60_000);\n return () => {\n cancelled = true;\n clearInterval(timerId);\n };\n }, [client]);\n\n const ssrFallback = props.ssrFallback ?? 'first';\n // Strip a trailing slash so consumers (devtools /explain, useAdaptiveApiBaseUrl)\n // build URLs the same way the core client does (it strips before appending\n // /events and /section-map) — otherwise an apiBaseUrl ending in \"/\" yields a\n // double slash like \".../v1//explain\".\n const apiBaseUrl = (props.apiBaseUrl ?? DEFAULT_API_BASE_URL).replace(/\\/$/, '');\n\n // The init effect above re-runs only on `props.consent`: apiKey / context /\n // country / apiBaseUrl are captured once and are deliberately stable for the\n // session, so changing them at runtime silently no-ops. That silence is\n // surprising — warn (dev only) when one actually changes value after init, so\n // the no-op is visible. To apply a new value, remount the provider (e.g. a\n // changing React `key`).\n const frozenConfigRef = useRef<{\n apiKey: string;\n context: SentientConfig['context'];\n country: string | undefined;\n apiBaseUrl: string;\n } | null>(null);\n useEffect(() => {\n if (typeof process !== 'undefined' && process.env?.NODE_ENV === 'production') return;\n const current = { apiKey: props.apiKey, context: props.context, country: props.country, apiBaseUrl };\n const prev = frozenConfigRef.current;\n frozenConfigRef.current = current;\n if (prev === null) return; // first run: capture the frozen baseline, nothing to compare\n for (const key of ['apiKey', 'context', 'country', 'apiBaseUrl'] as const) {\n if (!Object.is(prev[key], current[key])) {\n console.warn(\n `[sentient] AdaptiveProvider: \\`${key}\\` changed after initialisation, but the SDK client is stable for the session and only re-inits on \\`consent\\` — the new value is ignored. Remount the provider (e.g. via a changing \\`key\\` prop) to apply it.`,\n );\n }\n }\n }, [props.apiKey, props.context, props.country, apiBaseUrl]);\n\n // Publish devtools config through window: the /devtools entry is a separate\n // bundle and cannot read this provider's context instance. Dev-only.\n useEffect(() => {\n if (typeof process !== 'undefined' && process.env?.NODE_ENV === 'production') return;\n publishDevtoolsConfig({\n apiKey: props.apiKey,\n apiBaseUrl,\n isLocal: client?.isLocal === true,\n });\n }, [client, props.apiKey, apiBaseUrl]);\n\n // Sections registry for devtools /v1/explain + local simulation. The decided\n // order wins when there is one (it is what the page is actually rendering);\n // the declared list is the fallback so the layout panel still knows what is\n // reorderable when no decision arrived.\n useEffect(() => {\n const decided = props.initialLayoutOrder;\n if (decided && decided.length > 0) {\n registerSections(decided);\n return;\n }\n if (props.declaredSections && props.declaredSections.length > 0) {\n registerSections(props.declaredSections);\n }\n }, [props.initialLayoutOrder, props.declaredSections]);\n\n // The client exposed to consumers — wrapped to suppress events while previewing.\n const exposedClient = useMemo(\n () => (client && previewOn ? createPreviewClient(client) : client),\n [client, previewOn],\n );\n\n // Memoized so unrelated parent re-renders don't cascade through every\n // useSentient / useAssignment consumer via a fresh context object.\n const value = useMemo<AdaptiveContextValue>(\n () => ({\n client: exposedClient,\n apiKey: props.apiKey,\n initialAssignments: props.initialAssignments ?? {},\n sessionSegment,\n ssrFallback,\n onAssignment: props.onAssignment,\n initialLayoutOrder: props.initialLayoutOrder ?? null,\n initialSlots: props.initialSlots ?? {},\n initialPersona: props.initialPersona ?? null,\n apiBaseUrl,\n debug: props.debug ?? false,\n }),\n [\n exposedClient,\n props.apiKey,\n props.initialAssignments,\n sessionSegment,\n ssrFallback,\n props.onAssignment,\n props.initialLayoutOrder,\n props.initialSlots,\n props.initialPersona,\n apiBaseUrl,\n props.debug,\n ],\n );\n\n return (\n <AdaptiveContext.Provider value={value}>\n {props.children}\n </AdaptiveContext.Provider>\n );\n}\n\n/**\n * Returns the SentientClient, or null until the provider has finished\n * initialising on the client.\n */\nexport function useSentient(): SentientClient | null {\n return useContext(AdaptiveContext).client;\n}\n\n/** Internal: publishable API key carried alongside the client. */\nexport function useAdaptiveApiKey(): string {\n return useContext(AdaptiveContext).apiKey;\n}\n\n/** Internal: SSR-preloaded assignments for hydration-safe first render. */\nexport function useInitialAssignments(): Record<string, string> {\n return useContext(AdaptiveContext).initialAssignments;\n}\n\n/** Internal: bandit segment aligned with SSR session upsert. */\nexport function useSessionSegment(): string {\n return useContext(AdaptiveContext).sessionSegment;\n}\n\n/** Internal: SSR fallback strategy when a slot has no preloaded assignment. */\nexport function useSsrFallback(): SsrFallback {\n return useContext(AdaptiveContext).ssrFallback;\n}\n\n/** Internal: forwarding hook for consumer analytics integration. */\nexport function useOnAssignment(): ((componentId: string, variantId: string) => void) | undefined {\n return useContext(AdaptiveContext).onAssignment;\n}\n\n/** Internal: debug flag from the provider config, for dev-only diagnostic logging. */\nexport function useDebug(): boolean {\n return useContext(AdaptiveContext).debug;\n}\n\n/**\n * Returns the persona-specific section order from SSR, or null when no\n * sections were declared on AdaptiveRoot or reliability is below threshold.\n * Devtools/testing can force it via `window.__sentient_layout_override`;\n * consumers re-render when the devtools notifies an override change.\n */\nexport function useLayoutOrder(): string[] | null {\n const contextOrder = useContext(AdaptiveContext).initialLayoutOrder;\n const override = useSyncExternalStore(\n subscribeOverridesChanged,\n () =>\n typeof window === 'undefined'\n ? null\n : ((window as unknown as { __sentient_layout_override?: string[] })\n .__sentient_layout_override ?? null),\n () => null,\n );\n return override ?? contextOrder;\n}\n\n/** Internal: SSR-preloaded slot results for hydration-safe first render. */\nexport function useInitialSlots(): Record<string, SlotResult> {\n return useContext(AdaptiveContext).initialSlots;\n}\n\n/** Internal: SSR-decided persona carried alongside the client. */\nexport function useInitialPersona(): { persona: string; confidence: number } | null {\n return useContext(AdaptiveContext).initialPersona;\n}\n\n/** Internal: configured API base URL (devtools fetches /v1/explain against this, never a relative URL). */\nexport function useAdaptiveApiBaseUrl(): string {\n return useContext(AdaptiveContext).apiBaseUrl;\n}\n","/** Per-component weights store with isolated subscriptions. */\n\nexport type VariantWeight = {\n variantId: string;\n pulls: number;\n avgReward: number;\n};\n\nexport type ComponentWeights = {\n componentId: string;\n variants: VariantWeight[];\n updatedAt: number;\n};\n\ntype Listener = (weights: ComponentWeights) => void;\n\nconst store = new Map<string, ComponentWeights>();\nconst listeners = new Map<string, Set<Listener>>();\n\n/**\n * Subscribes a listener to a single component. Returns an unsubscribe function.\n * Updates to other components never trigger this listener.\n */\nexport function subscribe(componentId: string, cb: Listener): () => void {\n let set = listeners.get(componentId);\n if (!set) {\n set = new Set();\n listeners.set(componentId, set);\n }\n set.add(cb);\n return () => {\n set!.delete(cb);\n if (set!.size === 0) listeners.delete(componentId);\n };\n}\n\n/**\n * Replaces the weights for a component and notifies only that component's\n * subscribers.\n */\nexport function update(componentId: string, weights: ComponentWeights): void {\n store.set(componentId, weights);\n const set = listeners.get(componentId);\n if (!set) return;\n for (const cb of set) {\n try {\n cb(weights);\n } catch {\n /* never throw to other listeners */\n }\n }\n}\n\n/**\n * Returns the latest known weights for a component, or null if none seen.\n */\nexport function getWeights(componentId: string): ComponentWeights | null {\n return store.get(componentId) ?? null;\n}\n\n/** Test-only: wipe the entire store. */\nexport function _resetWeightsStore(): void {\n store.clear();\n listeners.clear();\n}\n","import type { SentientClient } from '@sentientui/core';\n\ntype PreviewState = { on: boolean; listeners: Set<() => void> };\nconst ssrFallback: PreviewState = { on: false, listeners: new Set() };\n\n// Window-backed: the /devtools entry (a separate bundle) toggles preview mode\n// and the provider (main bundle) must observe it.\nfunction state(): PreviewState {\n if (typeof window === 'undefined') return ssrFallback;\n const w = window as unknown as { __sentient_preview?: PreviewState };\n if (!w.__sentient_preview) w.__sentient_preview = { on: false, listeners: new Set() };\n return w.__sentient_preview;\n}\n\nexport function setPreviewMode(on: boolean): void {\n const s = state();\n if (s.on === on) return;\n s.on = on;\n for (const fn of s.listeners) fn();\n}\n\nexport function getPreviewMode(): boolean {\n return state().on;\n}\n\nexport function subscribePreview(fn: () => void): () => void {\n const listeners = state().listeners;\n listeners.add(fn);\n return () => {\n listeners.delete(fn);\n };\n}\n\n/**\n * Wraps a client so it writes nothing: reads pass through, all emitters no-op.\n * Used while previewing variants/personas so no `variant_assigned`, goal, or\n * session events are sent.\n */\nexport function createPreviewClient(inner: SentientClient): SentientClient {\n return {\n isLocal: inner.isLocal,\n track: () => undefined,\n goal: () => undefined,\n componentGoal: () => undefined,\n identify: () => undefined,\n fetchWeights: () => Promise.resolve([]),\n getAssignment: (componentId, segment) => inner.getAssignment(componentId, segment),\n assign: (componentId, variantIds, agentData, agentDataByVariant) =>\n inner.assign(componentId, variantIds, agentData, agentDataByVariant),\n // Reads pass through; decide is a write (slot decisions persist server-side)\n // so preview mode never issues it.\n decide: () => Promise.resolve(null),\n getSlotResult: (slotId) => inner.getSlotResult(slotId),\n getPersona: () => inner.getPersona(),\n getGraph: () => inner.getGraph(),\n dispose: () => inner.dispose(),\n destroy: () => inner.destroy(),\n };\n}\n","/**\n * Cross-bundle re-render bus for devtools overrides. The main entry and the\n * /devtools entry are separate bundles, so state and notifications go through\n * window (a version counter + a DOM event) — never module-local state.\n */\nconst EVENT = 'sentient:overrides-changed';\n\ntype VersionWindow = Window & { __sentient_overrides_version?: number };\n\nexport function getOverridesVersion(): number {\n if (typeof window === 'undefined') return 0;\n return (window as VersionWindow).__sentient_overrides_version ?? 0;\n}\n\nexport function notifyOverridesChanged(): void {\n if (typeof window === 'undefined') return;\n const w = window as VersionWindow;\n w.__sentient_overrides_version = (w.__sentient_overrides_version ?? 0) + 1;\n window.dispatchEvent(new Event(EVENT));\n}\n\nexport function subscribeOverridesChanged(fn: () => void): () => void {\n if (typeof window === 'undefined') return () => undefined;\n window.addEventListener(EVENT, fn);\n return () => window.removeEventListener(EVENT, fn);\n}\n","/** Provider → devtools config handoff. Window-backed: the /devtools entry is a\n * separate bundle and cannot share the provider's React context instance. */\nexport type DevtoolsConfig = {\n apiKey: string;\n apiBaseUrl: string;\n isLocal: boolean;\n};\n\ntype ConfigWindow = Window & { __sentient_devtools_config?: DevtoolsConfig };\n\nexport function publishDevtoolsConfig(config: DevtoolsConfig): void {\n if (typeof window === 'undefined') return;\n (window as ConfigWindow).__sentient_devtools_config = config;\n}\n\nexport function readDevtoolsConfig(): DevtoolsConfig | null {\n if (typeof window === 'undefined') return null;\n return (window as ConfigWindow).__sentient_devtools_config ?? null;\n}\n","import type { SentientClient } from '@sentientui/core';\n\ndeclare const process: { env?: { NODE_ENV?: string } } | undefined;\n\n/**\n * True unless NODE_ENV is 'production'. Never `process?.env` — optional\n * chaining still throws ReferenceError on an undeclared global, and browsers\n * without a bundler shim (raw esbuild, vanilla script tags) have no `process`.\n */\nexport function isDevBuild(): boolean {\n return typeof process === 'undefined' || process.env?.NODE_ENV !== 'production';\n}\n\nexport type ScrollDepthGoal = { type: 'scroll_depth'; threshold: number; value?: number };\nexport type ClickGoal = { type: 'click'; selector?: string; value?: number };\nexport type FormSubmitGoal = { type: 'form_submit'; value?: number };\nexport type CompositeGoal = { type: 'composite'; all: GoalConfig[] };\nexport type WeightedStep = { goal: GoalConfig; name: string; weight: number };\nexport type WeightedCompositeGoal = { type: 'weighted_composite'; steps: WeightedStep[] };\nexport type GoalConfig = ScrollDepthGoal | ClickGoal | FormSubmitGoal | CompositeGoal | WeightedCompositeGoal;\n\nexport function normalizeGoal(goal: string | GoalConfig): GoalConfig {\n if (typeof goal === 'string') return { type: 'click' };\n return goal;\n}\n\n/** The goalType label events are recorded under (named goal or config type). */\nexport function goalLabelOf(goal: string | GoalConfig): string {\n return typeof goal === 'string' ? goal : goal.type;\n}\n\n/** Static revenue value declared on a simple goal config, if any. Composites\n * carry no value (weights and values don't mix — spec §9.4); dynamic values\n * go through the imperative hooks. */\nexport function goalValueOf(goal: string | GoalConfig): number | undefined {\n if (typeof goal === 'string') return undefined;\n if (goal.type === 'click' || goal.type === 'form_submit' || goal.type === 'scroll_depth') {\n return goal.value;\n }\n return undefined;\n}\n\nfunction isClickableTarget(el: EventTarget | null): boolean {\n if (!(el instanceof Element)) return false;\n const tag = el.tagName.toLowerCase();\n if (tag === 'a' || tag === 'button') return true;\n const role = el.getAttribute('role');\n return role === 'button';\n}\n\nfunction findClickable(start: Element, container: Element, selector?: string): boolean {\n if (selector) {\n try {\n let cursor: Element | null = start;\n while (cursor && cursor !== container) {\n if (cursor.matches(selector)) return true;\n cursor = cursor.parentElement;\n }\n } catch {\n // Invalid CSS selector — treat as no match rather than breaking all click handlers.\n }\n return false;\n }\n let cursor: Element | null = start;\n while (cursor && cursor !== container) {\n if (isClickableTarget(cursor)) return true;\n cursor = cursor.parentElement;\n }\n return false;\n}\n\nexport type GoalHandlers = {\n /** Primary goal completion. Latch-once semantics are the CALLER's job. */\n fireGoal: () => void;\n /** Weighted-composite step completion (already deduped per step here). */\n fireStep: (name: string, weight: number, stepIndex: number) => void;\n};\n\n/**\n * Attaches the goal-detection listeners `<Adaptive>`'s container uses —\n * click / form_submit / scroll_depth, composite (all-of), and\n * weighted_composite (independent steps). Returns the cleanup function.\n * Extracted from adaptive.tsx so useAdaptive / useAdaptiveTokens /\n * AdaptiveGroup wire the SAME machinery instead of duplicating it.\n */\nexport function attachGoalListeners(node: Element, goal: GoalConfig, handlers: GoalHandlers): () => void {\n // --- Weighted composite: each step fires independently as it completes ---\n if (goal.type === 'weighted_composite') {\n const firedSteps = new Set<number>();\n const wcCleanups: Array<() => void> = [];\n\n goal.steps.forEach(({ goal: sub, name: stepName, weight: stepWeight }, idx) => {\n const fireStep = (): void => {\n if (firedSteps.has(idx)) return;\n firedSteps.add(idx);\n handlers.fireStep(stepName, stepWeight, idx);\n };\n\n if (sub.type === 'click') {\n const onClick = (e: Event): void => {\n const target = e.target;\n if (!(target instanceof Element)) return;\n if (!findClickable(target, node, sub.selector)) return;\n fireStep();\n };\n node.addEventListener('click', onClick);\n wcCleanups.push(() => node.removeEventListener('click', onClick));\n return;\n }\n\n if (sub.type === 'form_submit') {\n const onSubmit = (e: Event): void => {\n if (!(e.target instanceof HTMLFormElement)) return;\n if (!node.contains(e.target)) return;\n fireStep();\n };\n node.addEventListener('submit', onSubmit);\n wcCleanups.push(() => node.removeEventListener('submit', onSubmit));\n return;\n }\n\n if (sub.type === 'scroll_depth') {\n const threshold = Math.max(0, Math.min(1, sub.threshold));\n const io = new IntersectionObserver(\n (entries) => {\n for (const entry of entries) {\n if (entry.intersectionRatio >= threshold) {\n fireStep();\n io.disconnect();\n break;\n }\n }\n },\n { threshold: [threshold] },\n );\n io.observe(node);\n wcCleanups.push(() => io.disconnect());\n }\n });\n\n return () => {\n for (const c of wcCleanups) c();\n };\n }\n // --- End weighted composite ---\n\n const subgoals: GoalConfig[] = goal.type === 'composite' ? goal.all : [goal];\n const remaining = new Set<number>(subgoals.map((_, i) => i));\n const checkComposite = (idx: number): void => {\n remaining.delete(idx);\n if (remaining.size === 0) handlers.fireGoal();\n };\n\n const cleanups: Array<() => void> = [];\n\n subgoals.forEach((sub, idx) => {\n if (sub.type === 'click') {\n const onClick = (e: Event): void => {\n const target = e.target;\n if (!(target instanceof Element)) return;\n if (!findClickable(target, node, sub.selector)) return;\n if (goal.type === 'composite') checkComposite(idx);\n else handlers.fireGoal();\n };\n node.addEventListener('click', onClick);\n cleanups.push(() => node.removeEventListener('click', onClick));\n return;\n }\n\n if (sub.type === 'form_submit') {\n const onSubmit = (e: Event): void => {\n if (!(e.target instanceof HTMLFormElement)) return;\n if (!node.contains(e.target)) return;\n if (goal.type === 'composite') checkComposite(idx);\n else handlers.fireGoal();\n };\n node.addEventListener('submit', onSubmit);\n cleanups.push(() => node.removeEventListener('submit', onSubmit));\n return;\n }\n\n if (sub.type === 'scroll_depth') {\n const threshold = Math.max(0, Math.min(1, sub.threshold));\n const io = new IntersectionObserver(\n (entries) => {\n for (const entry of entries) {\n if (entry.intersectionRatio >= threshold) {\n if (goal.type === 'composite') checkComposite(idx);\n else handlers.fireGoal();\n io.disconnect();\n break;\n }\n }\n },\n { threshold: [threshold] },\n );\n io.observe(node);\n cleanups.push(() => io.disconnect());\n return;\n }\n });\n\n return () => {\n for (const c of cleanups) c();\n };\n}\n\n/**\n * Records the `variant_assigned` exposure event.\n */\nexport function trackExposure(\n client: SentientClient,\n apiKey: string,\n componentId: string,\n variantId: string,\n): void {\n client.track({\n projectId: apiKey,\n componentId,\n variantId,\n eventType: 'variant_assigned',\n payload: {},\n });\n}\n","import { isDevBuild } from './adaptive-shared.js';\n\nexport type RegisteredComponent = { id: string; variantIds: string[]; goal?: string };\nexport type RegisteredSlot = {\n id: string;\n arms?: string[];\n dims?: Record<string, readonly string[]>;\n};\n\ntype RegistryState = {\n components: Map<string, RegisteredComponent>;\n slots: Map<string, RegisteredSlot>;\n sections: string[];\n listeners: Set<() => void>;\n /** Bumped on every mutation so `useSyncExternalStore` can read a stable, comparable snapshot. */\n version: number;\n};\n\n// Shared through a window global: the main entry and the /devtools entry are\n// separate bundles, each with its own copy of this module — module-local\n// state would give the devtools an always-empty registry in published apps.\nconst ssrFallback: RegistryState = {\n components: new Map(),\n slots: new Map(),\n sections: [],\n listeners: new Set(),\n version: 0,\n};\n\nfunction state(): RegistryState {\n if (typeof window === 'undefined') return ssrFallback;\n const w = window as unknown as { __sentient_registry?: RegistryState };\n if (!w.__sentient_registry) {\n w.__sentient_registry = {\n components: new Map(),\n slots: new Map(),\n sections: [],\n listeners: new Set(),\n version: 0,\n };\n }\n return w.__sentient_registry;\n}\n\nfunction emit(): void {\n // Bump BEFORE notifying so a useSyncExternalStore consumer re-reading its\n // snapshot inside the notification sees the new value and re-renders.\n state().version += 1;\n for (const fn of state().listeners) fn();\n}\n\n// The registry exists solely to feed the opt-in devtools panel, which is a\n// dev-only surface. In a production build there is no panel reading it, so\n// every register call is dead work plus a `window.__sentient_registry`\n// footprint on the customer's page. Short-circuit to a noop in production —\n// every <Adaptive>/useAdaptive/slot mount calls one of these.\nconst NOOP_UNREGISTER = (): void => undefined;\n\n/** Register (or re-register) a component. Returns an unregister function. */\nexport function registerComponent(c: RegisteredComponent): () => void {\n if (!isDevBuild()) return NOOP_UNREGISTER;\n state().components.set(c.id, c);\n emit();\n return () => {\n state().components.delete(c.id);\n emit();\n };\n}\n\n/** Register (or re-register) a slot declaration. Returns an unregister function. */\nexport function registerSlot(s: RegisteredSlot): () => void {\n if (!isDevBuild()) return NOOP_UNREGISTER;\n state().slots.set(s.id, s);\n emit();\n return () => {\n state().slots.delete(s.id);\n emit();\n };\n}\n\n/** Register the page's declared section ids (from AdaptiveRoot/provider). */\nexport function registerSections(sections: string[]): void {\n if (!isDevBuild()) return;\n state().sections = [...sections];\n emit();\n}\n\nexport function getRegistered(): RegisteredComponent[] {\n return [...state().components.values()];\n}\n\nexport function getRegisteredSlots(): RegisteredSlot[] {\n return [...state().slots.values()];\n}\n\nexport function getRegisteredSections(): string[] {\n return [...state().sections];\n}\n\nexport function subscribeRegistry(fn: () => void): () => void {\n const listeners = state().listeners;\n listeners.add(fn);\n return () => {\n listeners.delete(fn);\n };\n}\n\n/** Monotonic snapshot for `useSyncExternalStore` — changes on every registry mutation. */\nexport function getRegistryVersion(): number {\n return state().version;\n}\n","'use client';\n\nimport { memo, useEffect, useMemo, useRef, useState, type ReactNode } from 'react';\nimport { attachMicroSignalDetectors, type MicroSignalType } from '@sentientui/core';\nimport { useAdaptiveApiKey, useSentient } from './provider.js';\nimport { useAssignment } from './use-assignment.js';\nimport { registerComponent } from './devtools-registry.js';\n\nexport type {\n ScrollDepthGoal,\n ClickGoal,\n FormSubmitGoal,\n CompositeGoal,\n WeightedStep,\n WeightedCompositeGoal,\n GoalConfig,\n} from './adaptive-shared.js';\nimport { attachGoalListeners, goalValueOf, isDevBuild, normalizeGoal, trackExposure, type GoalConfig } from './adaptive-shared.js';\n\n/** Maps a detected micro-signal to a named session goal (`client.goal`). */\nexport type MicroSignalGoalConfig = string | { name: string; weight?: number; stepIndex?: number };\nexport type MicroSignalGoals = Partial<Record<MicroSignalType, MicroSignalGoalConfig>>;\n\nexport type AdaptiveProps = {\n id: string;\n variants: Record<string, ReactNode>;\n goal: string | GoalConfig;\n /**\n * When a passive micro-signal fires on this component, also record a named goal.\n * Use for inferred goals surfaced in the dashboard (e.g. rage_click → 'confused_by_hero').\n */\n microSignalGoals?: MicroSignalGoals;\n /**\n * When true, renders nothing during SSR and before client hydration.\n * Use when you cannot pass `initialAssignments` and prefer a blank slot over\n * a hydration mismatch. Tradeoff: minor CLS on first paint.\n */\n clientOnly?: boolean;\n /**\n * Variant-specific structured data for AI agent consumption via /sentient.json and\n * GET /v1/agent/layout. Keyed by variant ID — only the assigned variant's entry is stored,\n * so agents see only the content currently being served to visitors.\n *\n * Prefer this over `agentData` when variants have meaningfully different content.\n *\n * Captured at MOUNT: this value is read once, when the component's assignment\n * is requested, and is intentionally not part of the assign effect's deps.\n * Changing it after mount does not re-send it — pass the final value on first\n * render (e.g. from SSR/loader data, not a value that streams in later).\n */\n agentDataByVariant?: Record<string, unknown>;\n /**\n * @deprecated Use agentDataByVariant for variant-specific content. Stored as-is for the assigned variant.\n *\n * Captured at MOUNT (see `agentDataByVariant`): changing it after mount has no\n * effect on what is sent for the assignment.\n */\n agentData?: unknown;\n};\n\nfunction AdaptiveImpl(props: AdaptiveProps): JSX.Element | null {\n const client = useSentient();\n const apiKey = useAdaptiveApiKey();\n // Freeze the variant-id array on the KEY SET, not the object identity: an\n // inline `variants={{...}}` literal is a fresh object every render, so keying\n // on `props.variants` churned a new array each commit — re-running the\n // register effect (dep below) and unregistering+re-registering the component\n // on every render. A joined-keys signature is stable across renders for the\n // same keys yet still updates if the declared set changes. Same convention as\n // useAdaptive / AdaptiveGroup / useAdaptiveTokens.\n const variantKey = Object.keys(props.variants).join('\\u0000');\n // eslint-disable-next-line react-hooks/exhaustive-deps\n const variantIds = useMemo(() => Object.keys(props.variants), [variantKey]);\n const { variantId, content, isOverride, settled } = useAssignment(props.id, variantIds, props.agentData, props.agentDataByVariant);\n const containerRef = useRef<HTMLDivElement>(null);\n const [mounted, setMounted] = useState(false);\n\n useEffect(() => { setMounted(true); }, []);\n const goalFiredRef = useRef(false);\n const microGoalFiredRef = useRef<Set<MicroSignalType>>(new Set());\n const assignTrackedRef = useRef<string | null>(null);\n const goalKey = typeof props.goal === 'string' ? props.goal : JSON.stringify(props.goal);\n const goal = useMemo(() => normalizeGoal(props.goal), [goalKey]);\n const goalLabel = typeof props.goal === 'string' ? props.goal : goal.type;\n\n // Register with the devtools registry so the dev widget can list this\n // component + its variants. Inert in production (registry has no UI); the\n // cleanup unregisters on unmount.\n useEffect(() => registerComponent({ id: props.id, variantIds, goal: goalLabel }), [props.id, variantIds, goalLabel]);\n\n // Track variant_assigned exactly once per (component, variant) mount.\n useEffect(() => {\n // A forced variant is a dev/test view, not a real exposure — recording it\n // would train the bandit on the override. Same gate on every tracking\n // effect below (\"no events recorded, weights unchanged\").\n if (isOverride) return;\n // Only expose a SETTLED assignment. On the CSR path the served variant\n // resolves in two steps (interim baseline variantIds[0] → bandit choice);\n // tracking the interim would accrue a phantom baseline exposure that can\n // never convert. Mirrors AdaptiveText (start null, track after settle).\n if (!settled) return;\n if (!client || !variantId || !apiKey) return;\n if (assignTrackedRef.current === variantId) return;\n assignTrackedRef.current = variantId;\n trackExposure(client, apiKey, props.id, variantId);\n }, [client, variantId, apiKey, props.id, isOverride, settled]);\n\n // Reset goal latch when variant or goal changes.\n useEffect(() => {\n goalFiredRef.current = false;\n microGoalFiredRef.current = new Set();\n }, [variantId, goal]);\n\n // Emit cursor_signal after 800 ms of continuous hover.\n useEffect(() => {\n if (isOverride) return;\n // Same settle gate as the exposure: before assign() resolves, variantId is\n // the interim baseline placeholder — a hover then would attribute a\n // cursor_signal to an arm that was never really served.\n if (!settled) return;\n if (!client || !variantId) return;\n const node = containerRef.current;\n if (!node) return;\n\n let timerId: ReturnType<typeof setTimeout> | null = null;\n let hoverStart = 0;\n\n const onEnter = (): void => {\n hoverStart = Date.now();\n timerId = setTimeout(() => {\n client.track({\n projectId: apiKey,\n componentId: props.id,\n variantId: variantId!,\n eventType: 'cursor_signal',\n payload: { hoverDuration: Date.now() - hoverStart },\n });\n timerId = null;\n }, 800);\n };\n\n const onLeave = (): void => {\n if (timerId !== null) {\n clearTimeout(timerId);\n timerId = null;\n }\n };\n\n node.addEventListener('mouseenter', onEnter);\n node.addEventListener('mouseleave', onLeave);\n return () => {\n node.removeEventListener('mouseenter', onEnter);\n node.removeEventListener('mouseleave', onLeave);\n if (timerId !== null) clearTimeout(timerId);\n };\n }, [client, variantId, apiKey, props.id, isOverride, settled]);\n\n // Attach micro-signal detectors passively — rage click, text copy, scroll hesitation, tab loss.\n useEffect(() => {\n if (isOverride) return;\n // Gate on settle too (like the exposure): during the pre-assign() window\n // variantId is the interim baseline placeholder, so a rage-click / tab-loss\n // would record a micro_signal — and fire a mapped named goal — attributed\n // to an arm that was never really served.\n if (!settled) return;\n if (!client || !variantId) return;\n const node = containerRef.current;\n if (!node) return;\n const assignedAt = Date.now();\n return attachMicroSignalDetectors(\n (signalType, extra = {}) => {\n client.track({\n projectId: apiKey,\n componentId: props.id,\n variantId: variantId!,\n eventType: 'micro_signal',\n payload: { signalType, ...extra },\n });\n\n const mapping = props.microSignalGoals?.[signalType];\n if (!mapping || microGoalFiredRef.current.has(signalType)) return;\n microGoalFiredRef.current.add(signalType);\n const name = typeof mapping === 'string' ? mapping : mapping.name;\n const weight = typeof mapping === 'string' ? 1.0 : (mapping.weight ?? 1.0);\n const stepIndex = typeof mapping === 'string' ? 0 : (mapping.stepIndex ?? 0);\n // Explicit options form: `extra` is arbitrary micro-signal data, so it\n // must land in metadata and never be mistaken for GoalOptions keys.\n client.goal(name, { metadata: { signalType, ...extra }, weight, stepIndex });\n },\n node,\n assignedAt,\n );\n }, [client, variantId, apiKey, props.id, props.microSignalGoals, isOverride, settled]);\n\n // Attach goal tracking (shared machinery — see adaptive-shared.ts).\n useEffect(() => {\n if (isOverride) return;\n if (!client || !variantId) return;\n const node = containerRef.current;\n if (!node) return;\n\n // A static `value` on the goal config rides on BOTH writes (the component-\n // attributed event and the session funnel record) so read-time dedup never\n // picks a valueless row. Steps carry weights, never values (spec §9.4).\n const declaredValue = goalValueOf(goal);\n return attachGoalListeners(node, goal, {\n fireGoal: () => {\n if (goalFiredRef.current) return;\n goalFiredRef.current = true;\n client.track({\n projectId: apiKey,\n componentId: props.id,\n variantId,\n eventType: 'goal_achieved',\n goalType: goalLabel,\n payload: { reward: 1.0, ...(declaredValue !== undefined ? { goalValue: declaredValue } : {}) },\n });\n client.goal(goalLabel, {\n metadata: { componentId: props.id, variantId },\n weight: 1.0,\n stepIndex: 0,\n ...(declaredValue !== undefined ? { value: declaredValue } : {}),\n });\n },\n fireStep: (name, weight, stepIndex) => {\n client.track({\n projectId: apiKey,\n componentId: props.id,\n variantId: variantId!,\n eventType: 'goal_achieved',\n goalType: name,\n payload: { reward: weight },\n });\n client.goal(name, { metadata: {}, weight, stepIndex });\n },\n });\n }, [client, variantId, apiKey, props.id, goal, goalLabel, isOverride]);\n\n // Decorative slots: empty in SSR HTML and until the client has mounted.\n if (props.clientOnly && (!mounted || !client)) return null;\n if (!variantId) return null;\n\n const jsxContent = props.variants[variantId] ?? null;\n const managedContent = jsxContent === null ? content : null;\n\n if (isDevBuild() && jsxContent === null && managedContent === null) {\n console.warn(\n `[sentient] <Adaptive id=\"${props.id}\"> was assigned variant \"${variantId}\" but no matching key exists in props.variants.` +\n ` If this is a dashboard-managed text variant, use <AdaptiveText id=\"${props.id}\"> instead.`,\n );\n }\n\n return (\n <div ref={containerRef} data-sentient-id={props.id} data-sentient-variant={variantId}>\n {jsxContent ?? managedContent}\n </div>\n );\n}\n\n/**\n * Skips re-render only when nothing the output depends on has changed. The\n * variant node values must be compared, not just their keys: the assigned\n * `variantId` is stable, so if we compared keys alone, dynamic content inside a\n * variant (e.g. `<Price value={price}/>`) would render once and then freeze when\n * `price` changes. Elements are compared by reference — a caller that recreates\n * variant JSX on every render re-renders every time (correct), while stable/\n * memoized elements keep the optimization.\n */\nexport const Adaptive = memo(AdaptiveImpl, (prev, next) => {\n if (prev.id !== next.id) return false;\n // Serialize only when the goal reference actually changed — a stable/memoized\n // goal (the common case) skips the stringify entirely.\n if (prev.goal !== next.goal && JSON.stringify(prev.goal) !== JSON.stringify(next.goal)) return false;\n if (prev.microSignalGoals !== next.microSignalGoals) return false;\n if (prev.clientOnly !== next.clientOnly) return false;\n if (prev.agentData !== next.agentData) return false;\n if (prev.agentDataByVariant !== next.agentDataByVariant) return false;\n if (prev.variants === next.variants) return true;\n const prevKeys = Object.keys(prev.variants);\n const nextKeys = Object.keys(next.variants);\n if (prevKeys.length !== nextKeys.length) return false;\n return prevKeys.every((k) => k in next.variants && Object.is(prev.variants[k], next.variants[k]));\n});\n","import { useEffect, useRef, useState, useSyncExternalStore } from 'react';\nimport { type AssignResult } from '@sentientui/core';\nimport { useSentient, useInitialAssignments, useSessionSegment, useSsrFallback, useOnAssignment, useDebug } from './provider.js';\nimport { subscribe, getWeights, type ComponentWeights } from './weights-store.js';\nimport { subscribeOverridesChanged } from './override-events.js';\nimport { getDevOverride } from './dev-override.js';\n\nexport type AssignmentState = {\n variantId: string | null;\n /** Populated when the assigned variant is a dashboard-managed text variant. */\n content: string | null;\n isLoading: boolean;\n /**\n * True once `variantId` reflects a REAL decision — an SSR preload, the local\n * assignment cache, a server `assign()`, live bandit weights, or a dev\n * override — rather than the interim `variantIds[0]` placeholder shown while a\n * decision is still in flight. Exposure tracking MUST gate on this: emitting\n * `variant_assigned` for the placeholder accrues a phantom baseline\n * impression that can never convert and dilutes that arm's CVR.\n */\n settled: boolean;\n /**\n * True while a dev override (?sentient_variant= / window.__sentient_overrides)\n * is forcing this variant. Consumers must suppress ALL tracking while set —\n * the override contract is \"no events recorded, weights unchanged\".\n */\n isOverride?: boolean;\n};\n\n// Pseudo-count for the shrinkage prior below — the number of \"prior\" pulls at\n// reward 0 mixed into every arm's mean. Large enough to sink a lucky 1-pull\n// arm, small enough to be negligible once an arm has real traffic.\nconst PRIOR_PULLS = 5;\n\n/**\n * Degraded-fallback selection from cached bandit weights (used only when the\n * server assignment hasn't resolved). Ranks arms by a posterior mean shrunk\n * toward a zero prior — `pulls·avgReward / (pulls + PRIOR_PULLS)` — so a lucky\n * small-sample arm (e.g. 1 pull at avgReward 1.0) can't outrank a well-sampled\n * one (500 pulls at 0.2). With equal pulls the shrinkage is monotonic in\n * avgReward, preserving plain \"highest avgReward wins\" behavior.\n */\nfunction pickFromWeights(weights: ComponentWeights, variantIds: string[]): string | null {\n let best: { variantId: string; score: number } | null = null;\n for (const v of weights.variants) {\n if (!variantIds.includes(v.variantId)) continue;\n const pulls = v.pulls ?? 0;\n const score = pulls > 0 ? (pulls * v.avgReward) / (pulls + PRIOR_PULLS) : 0;\n if (!best || score > best.score) {\n best = { variantId: v.variantId, score };\n }\n }\n return best?.variantId ?? null;\n}\n\n/**\n * Returns a sticky variant assignment for a component.\n *\n * @deprecated Since 0.13.0 — use {@link useAdaptive} instead. `useAssignment`\n * only SELECTS a variant; it wires no exposure tracking, no goal listeners,\n * and no micro-signals, so components using it directly accumulate no\n * learning signal. It keeps working (it is `useAdaptive`'s internal\n * selection engine) but will move to internal-only in 1.0.0.\n *\n * First render reads the local SDK cache; if empty, falls back to a\n * deterministic default and asynchronously calls `/v1/assign`. The server\n * picks the actual variant via Thompson Sampling and the result replaces the fallback\n * on the next render. Subsequent paints read synchronously from cache —\n * no flicker, no loading state after first paint.\n */\nexport function useAssignment(componentId: string, variantIds: string[], agentData?: unknown, agentDataByVariant?: Record<string, unknown>): AssignmentState {\n const initialAssignments = useInitialAssignments();\n const ssrFallback = useSsrFallback();\n const client = useSentient();\n const segment = useSessionSegment();\n const onAssignment = useOnAssignment();\n const debug = useDebug();\n const assignmentReportedRef = useRef<string | null>(null);\n\n // Dev override (URL ?sentient_variant=componentId:variantId or\n // window.__sentient_overrides[componentId]) read through useSyncExternalStore:\n // - server snapshot is null (no window), so SSR renders the un-forced variant;\n // - the client snapshot reads the override, and React reconciles the two\n // across hydration WITHOUT a mismatch (this is exactly what the hook is for);\n // - unlike a post-mount flip it is already correct on a remount / CSR-nav, so\n // a forced variant never leaks an interim assign() or exposure before the\n // override applies.\n // It also re-renders when the devtools/scenario helpers bump the override bus.\n const devOverride = useSyncExternalStore(\n subscribeOverridesChanged,\n () => getDevOverride(componentId),\n () => null,\n );\n const overrideVariant = devOverride && variantIds.includes(devOverride) ? devOverride : null;\n const overrideLoggedRef = useRef<string | null>(null);\n // Diagnostic log for an active dev override — effect, never render body, and\n // gated behind the provider's debug flag so it stays silent in production.\n useEffect(() => {\n if (!debug) return;\n if (!overrideVariant) return;\n if (overrideLoggedRef.current === overrideVariant) return;\n overrideLoggedRef.current = overrideVariant;\n console.info(`[sentient] override active: ${componentId} -> ${overrideVariant}`);\n }, [debug, overrideVariant, componentId]);\n\n // Lazy initializer: this selection logic (URLSearchParams parse via the\n // override read above, cache + weights Map lookups) runs ONCE on mount, not\n // on every render. React only uses a useState initializer's value on first\n // render, so computing it eagerly each render was pure waste on every\n // <Adaptive>/useAdaptive re-render. Mirrors AdaptiveText's lazy seeds.\n const [state, setState] = useState<AssignmentState>((): AssignmentState => {\n if (overrideVariant) {\n return { variantId: overrideVariant, content: null, isLoading: false, settled: true };\n }\n // SSR / pre-hydration: no client yet. Use initialAssignments if provided so\n // the server and client first render agree on the same variant (no mismatch).\n if (!client) {\n const preloaded = initialAssignments[componentId];\n if (preloaded && variantIds.includes(preloaded)) {\n // Server-decided — a real assignment, safe to expose.\n return { variantId: preloaded, content: null, isLoading: false, settled: true };\n }\n if (ssrFallback === 'first' && variantIds.length > 0) {\n // SEO placeholder shown until the client resolves a real decision — NOT\n // settled, so no exposure fires for this interim baseline.\n return { variantId: variantIds[0], content: null, isLoading: false, settled: false };\n }\n return { variantId: null, content: null, isLoading: true, settled: false };\n }\n const cached = client.getAssignment(componentId, segment);\n // Allow cached managed variants (content present) even if not in variantIds.\n if (cached && (variantIds.includes(cached.variantId) || cached.content)) {\n return { variantId: cached.variantId, content: cached.content ?? null, isLoading: false, settled: true };\n }\n const weights = getWeights(componentId);\n if (weights) {\n const chosen = pickFromWeights(weights, variantIds);\n if (chosen) return { variantId: chosen, content: null, isLoading: false, settled: true };\n }\n // Interim placeholder while the async assign() below is in flight — not a\n // real decision yet, so it stays unsettled and emits no exposure.\n return { variantId: variantIds[0] ?? null, content: null, isLoading: false, settled: false };\n });\n\n // Helper: call onAssignment at most once per resolved variant.\n const reportAssignment = (variantId: string): void => {\n if (!onAssignment) return;\n if (assignmentReportedRef.current === variantId) return;\n assignmentReportedRef.current = variantId;\n onAssignment(componentId, variantId);\n };\n\n // As soon as the client is ready, unblock the UI immediately with variantIds[0]\n // (or a cached value) so the component never stays invisible while assign is\n // in-flight. The async assign call below then swaps to the bandit-chosen variant.\n useEffect(() => {\n if (overrideVariant) return;\n if (!client) return;\n const cached = client.getAssignment(componentId, segment);\n if (cached && (variantIds.includes(cached.variantId) || cached.content)) {\n setState({ variantId: cached.variantId, content: cached.content ?? null, isLoading: false, settled: true });\n reportAssignment(cached.variantId);\n return;\n }\n setState((prev) => prev.variantId ? prev : { variantId: variantIds[0] ?? null, content: null, isLoading: false, settled: false });\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [overrideVariant, client, componentId, segment]);\n\n // Ask the server for a real assignment when we have a client but no cached one.\n useEffect(() => {\n if (overrideVariant) return;\n if (!client) return;\n const cached = client.getAssignment(componentId, segment);\n if (cached && variantIds.includes(cached.variantId)) return;\n\n let cancelled = false;\n void client.assign(componentId, variantIds, agentData, agentDataByVariant).then((result: AssignResult | null) => {\n if (cancelled) return;\n if (!result) return;\n // Allow the result if it's a known code variant OR a managed text variant (has content).\n if (!variantIds.includes(result.variantId) && !result.content) return;\n setState({ variantId: result.variantId, content: result.content ?? null, isLoading: false, settled: true });\n reportAssignment(result.variantId);\n });\n return () => { cancelled = true; };\n // variantIds intentionally excluded — changing variants mid-mount is unsupported\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [overrideVariant, client, componentId, segment]);\n\n // Live weight updates from the dashboard SSE stream (when wired).\n useEffect(() => {\n if (overrideVariant) return;\n if (!client) return;\n return subscribe(componentId, (weights) => {\n const cached = client.getAssignment(componentId, segment);\n if (cached && (variantIds.includes(cached.variantId) || cached.content)) {\n setState({ variantId: cached.variantId, content: cached.content ?? null, isLoading: false, settled: true });\n return;\n }\n const chosen = pickFromWeights(weights, variantIds);\n if (chosen) setState({ variantId: chosen, content: null, isLoading: false, settled: true });\n });\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [overrideVariant, client, componentId, segment]);\n\n if (overrideVariant) {\n return { variantId: overrideVariant, content: null, isLoading: false, settled: true, isOverride: true };\n }\n\n return state;\n}\n","declare global {\n interface Window {\n __sentient_overrides?: Record<string, string>;\n }\n}\n\n/**\n * Reads a forced variant for a component from the dev-override channels:\n * `window.__sentient_overrides[id]` (devtools panel, `applyScenario`, the\n * Playwright/Cypress helpers) or the `?sentient_variant=id:variant` URL param\n * (repeatable for multiple components). Returns `null` in non-browser envs.\n *\n * Callers MUST read this POST-MOUNT (never in the render body): it touches\n * `window.location`, which is absent on the server, so reading it during render\n * diverges the SSR output from the client's first render and throws a hydration\n * mismatch on any SSR page carrying `?sentient_variant=`.\n */\nexport function getDevOverride(componentId: string): string | null {\n if (typeof window === 'undefined') return null;\n const global = window.__sentient_overrides?.[componentId];\n if (global) return global;\n // This runs as a useSyncExternalStore getSnapshot (once or twice per render\n // pass, per adaptive component), so skip the URLSearchParams parse entirely on\n // the overwhelmingly common no-query-string page.\n if (!window.location.search) return null;\n try {\n const params = new URLSearchParams(window.location.search);\n for (const raw of params.getAll('sentient_variant')) {\n // sentient_variant=componentId:variantId (repeatable for multiple components)\n const sep = raw.indexOf(':');\n if (sep === -1) continue;\n if (raw.slice(0, sep) === componentId) return raw.slice(sep + 1);\n }\n } catch {\n /* non-browser env */\n }\n return null;\n}\n","'use client';\n\nimport { useEffect, useMemo, useRef, useState, useSyncExternalStore, type ElementType } from 'react';\nimport type { AssignResult } from '@sentientui/core';\nimport { useSentient, useAdaptiveApiKey, useOnAssignment, useSessionSegment } from './provider.js';\nimport { attachGoalListeners, goalValueOf, isDevBuild, normalizeGoal, type GoalConfig } from './adaptive-shared.js';\nimport { getDevOverride } from './dev-override.js';\nimport { subscribeOverridesChanged } from './override-events.js';\n\n\nexport type AdaptiveTextProps = {\n id: string;\n default: string;\n component?: keyof JSX.IntrinsicElements;\n className?: string;\n /**\n * Optional conversion goal to optimize this copy toward. Without it, the\n * variant is served and logged but never scored — the copy rotates and never\n * learns. Provide a goal (a name string or a GoalConfig) to make the optimizer\n * attribute conversions to the winning wording, exactly like `<Adaptive>`.\n */\n goal?: string | GoalConfig;\n};\n\n/**\n * Dashboard-managed copy for a single element. The variants are **text only** —\n * they change the wording, never the CSS, markup, or layout of the element\n * (managed variants created from the dashboard/MCP carry text, nothing else).\n * For anything structural — style, markup shape, position — write the change in\n * code with `<Adaptive>` (any JSX per variant) or use adaptive slots on no-code\n * sites. Pass `goal` to make the managed copy optimizable (see below).\n */\nexport function AdaptiveText({\n id,\n default: defaultText,\n component: Tag = 'span',\n className,\n goal: goalProp,\n}: AdaptiveTextProps) {\n const client = useSentient();\n const apiKey = useAdaptiveApiKey();\n const onAssignment = useOnAssignment();\n const segment = useSessionSegment();\n const trackedRef = useRef<string | null>(null);\n const nodeRef = useRef<HTMLElement | null>(null);\n\n // Dev override parity with <Adaptive>/useAdaptive: honor\n // ?sentient_variant=id:variant and window.__sentient_overrides (devtools,\n // applyScenario, Playwright/Cypress). A forced variant is a preview — it\n // suppresses the network assign, exposure, and goals (\"no events recorded,\n // weights unchanged\"). Read through useSyncExternalStore (server snapshot\n // null → no hydration mismatch on a ?sentient_variant= page; client snapshot\n // synchronous → no interim assign() before the override applies on remount).\n const override = useSyncExternalStore(\n subscribeOverridesChanged,\n () => getDevOverride(id),\n () => null,\n );\n\n // Seed from cache synchronously so remounts don't flash back to defaultText.\n const [text, setText] = useState<string | null>(() =>\n client?.getAssignment(id, segment)?.content ?? null\n );\n const [variantId, setVariantId] = useState<string | null>(() =>\n client?.getAssignment(id, segment)?.variantId ?? null\n );\n\n useEffect(() => {\n if (override) return; // forced variant — no network assign\n if (!client) return;\n // Skip if content already cached; assign() re-checks internally but this avoids the async round-trip on remount.\n if (client.getAssignment(id, segment)?.content !== undefined) return;\n\n let cancelled = false;\n void client.assign(id).then((result: AssignResult | null) => {\n if (cancelled) return;\n if (!result) {\n if (isDevBuild()) {\n console.warn(`[sentient] <AdaptiveText id=\"${id}\"> assignment failed — showing default text.`);\n }\n return;\n }\n setVariantId(result.variantId);\n if (result.content) setText(result.content);\n });\n return () => {\n cancelled = true;\n };\n }, [client, id, segment, override]);\n\n useEffect(() => {\n if (override) return; // forced variant records no exposure\n if (!client || !variantId || !apiKey) return;\n if (trackedRef.current === variantId) return;\n trackedRef.current = variantId;\n client.track({\n projectId: apiKey,\n componentId: id,\n variantId,\n eventType: 'variant_assigned',\n payload: {},\n });\n onAssignment?.(id, variantId);\n }, [client, variantId, apiKey, id, onAssignment, override]);\n\n // Optional goal attribution (opt-in) — mirrors <Adaptive>. Without a goal the\n // copy is served but never scored.\n const goalKey = goalProp === undefined ? '' : typeof goalProp === 'string' ? goalProp : JSON.stringify(goalProp);\n const goal = useMemo(() => (goalProp === undefined ? null : normalizeGoal(goalProp)), [goalKey]);\n const goalLabel = goalProp === undefined ? null : typeof goalProp === 'string' ? goalProp : goal!.type;\n const goalFiredRef = useRef(false);\n\n useEffect(() => {\n goalFiredRef.current = false;\n }, [variantId, goalKey]);\n\n useEffect(() => {\n if (override) return; // forced variant records no goals\n if (!client || !variantId || !apiKey || !goal || !goalLabel) return;\n const node = nodeRef.current;\n if (!node) return;\n // A static goal-config value rides on both writes (spec §5).\n const declaredValue = goalValueOf(goal);\n return attachGoalListeners(node, goal, {\n fireGoal: () => {\n if (goalFiredRef.current) return;\n goalFiredRef.current = true;\n client.track({\n projectId: apiKey,\n componentId: id,\n variantId,\n eventType: 'goal_achieved',\n goalType: goalLabel,\n payload: { reward: 1.0, ...(declaredValue !== undefined ? { goalValue: declaredValue } : {}) },\n });\n client.goal(goalLabel, {\n metadata: { componentId: id, variantId },\n weight: 1.0,\n stepIndex: 0,\n ...(declaredValue !== undefined ? { value: declaredValue } : {}),\n });\n },\n fireStep: (name, weight, stepIndex) => {\n client.track({\n projectId: apiKey,\n componentId: id,\n variantId,\n eventType: 'goal_achieved',\n goalType: name,\n payload: { reward: weight },\n });\n client.goal(name, { metadata: {}, weight, stepIndex });\n },\n });\n }, [client, variantId, apiKey, id, goal, goalLabel, override]);\n\n // Under a forced override, show the override variant's managed copy only if\n // it happens to be cached (managed text lives server-side, so an arbitrary\n // forced variant has no client-available copy) — otherwise fall back to the\n // default. Without an override this is just the assigned/default text.\n let displayText = text ?? defaultText;\n if (override) {\n const cached = client?.getAssignment(id, segment);\n displayText = cached && cached.variantId === override ? (cached.content ?? defaultText) : defaultText;\n }\n\n // Cast to ElementType so a single ref callback works across every intrinsic\n // tag without exploding into the full HTML/SVG ref union.\n const Component = Tag as ElementType;\n return (\n <Component ref={(el: HTMLElement | null) => { nodeRef.current = el; }} className={className}>\n {displayText}\n </Component>\n );\n}\n","import { useCallback, useRef } from 'react';\nimport type { ComponentGoalOptions } from '@sentientui/core';\nimport { useSentient } from './provider.js';\nimport { getDevOverride } from './dev-override.js';\n\nexport interface FireGoalOptions extends ComponentGoalOptions {\n /**\n * Record this goal at most once per mounted component, however many times the\n * callback is invoked. Use it for conversions that are a state, not an action\n * — \"reached step 3\", \"form validated\", an effect that may re-run — where a\n * second record is double counting rather than a second conversion.\n *\n * Leave it off for genuine repeat actions (each click of \"add to cart\" is its\n * own conversion). The latch is per goal type and lives for the lifetime of\n * the component holding the callback, so a remount can record again.\n */\n once?: boolean;\n}\n\nexport type FireGoal = (goalType: string, opts?: FireGoalOptions) => void;\n\n/**\n * Returns a `fireGoal(goalType, opts?)` callback that records a conversion\n * attributed to the variant currently served for `componentId` — so it shows\n * up in the per-variant CVR funnel with no manual variantId/projectId plumbing.\n *\n * The served variant is resolved from the SDK's assignment cache (the same one\n * `<Adaptive id={componentId}>` populates), so render that component before\n * firing. Use this for imperative handlers (click, form submit, custom events);\n * for purely declarative goals prefer `<Adaptive goal={...}>`.\n *\n * Each call records one bandit reward event AND one session goal-funnel record.\n * It has no cross-call latch, so a component that *also* declares a matching\n * `<Adaptive goal>` (or fires this on every click) records one conversion per\n * call — keep goal labels unique per conversion so counts aren't inflated.\n *\n * @example\n * const fireContact = useAdaptiveGoal('hero_headline');\n * <button onClick={() => fireContact('hero_contact', { metadata: { method } })}>Call</button>\n */\nexport function useAdaptiveGoal(componentId: string): FireGoal {\n const client = useSentient();\n // Goal types already recorded through this callback, for `once`. A ref, not\n // state: latching must not re-render, and the set has to survive the callback\n // being recreated when the client arrives (consent granted mid-session).\n const firedOnce = useRef<Set<string>>(new Set());\n return useCallback<FireGoal>(\n (goalType, opts) => {\n // A forced variant (?sentient_variant= / window.__sentient_overrides) is a\n // dev/QA preview, not real traffic. Recording a goal would credit the\n // bandit and pollute the session funnel for the overridden arm — breaking\n // the \"no events recorded, weights unchanged\" override contract that\n // <Adaptive>, useAdaptive.fireGoal, and the declarative path all honor.\n // Read post-mount (inside the callback), never in a render body.\n // Checked BEFORE the `once` latch: a preview must not consume the one\n // record a real conversion is entitled to after the override clears.\n if (getDevOverride(componentId)) return;\n if (opts?.once) {\n if (firedOnce.current.has(goalType)) return;\n firedOnce.current.add(goalType);\n }\n // componentGoal credits the bandit (arm resolved from the assignment\n // cache); goal() writes the session-level conversion funnel record. A\n // declared <Adaptive goal> fires both — a manual conversion for the same\n // component must too, or it shows up in per-variant CVR but never in the\n // session goal funnel. Revenue fields ride on both writes so read-time\n // dedup never picks a valueless row (spec §5).\n client?.componentGoal(componentId, goalType, opts);\n client?.goal(goalType, {\n metadata: opts?.metadata ?? {},\n weight: opts?.reward ?? 1.0,\n stepIndex: 0,\n ...(opts?.value !== undefined ? { value: opts.value } : {}),\n ...(opts?.currency !== undefined ? { currency: opts.currency } : {}),\n ...(opts?.externalId !== undefined ? { externalId: opts.externalId } : {}),\n });\n },\n [client, componentId],\n );\n}\n","import { useEffect, useRef } from 'react';\nimport type { ComponentGoalOptions } from '@sentientui/core';\nimport { useSentient } from './provider.js';\nimport { useAdaptiveGoal } from './use-adaptive-goal.js';\n\nexport interface PageGoalOptions extends ComponentGoalOptions {\n /**\n * Credit the arrival to the variant currently served for this component —\n * typically the CTA on the page the visitor came FROM. The served variant is\n * read from the assignment cache, which is localStorage-backed, so the credit\n * survives the navigation. Omit for a session-level goal with no per-variant\n * attribution.\n */\n componentId?: string;\n}\n\n/**\n * Records `goalName` once, when a page or route is reached.\n *\n * Use this for funnel steps that are a *destination* rather than a click:\n * reaching /pricing, landing on a signup form, opening a checkout. Arrival is\n * the better signal — it survives the navigation that a click goal can lose,\n * and it also counts visitors who arrived from the nav, a search result or a\n * shared link, none of whom clicked the CTA being measured.\n *\n * Two things this handles that hand-rolling `useAdaptiveGoal` in an effect does\n * not, both of which fail silently:\n *\n * - **Fires once.** `useAdaptiveGoal` has no latch, so a remount — or React's\n * double-invoked effects in development — records the same arrival twice and\n * inflates the funnel.\n * - **Waits for consent.** Under a consent gate the client does not exist when\n * the page mounts, and a visitor who accepts a moment later would lose the\n * goal entirely. The arrival is held until the SDK is running, then sent.\n *\n * Safe during SSR (effects do not run on the server) and a no-op without a\n * provider above it.\n *\n * @example\n * // Credit reaching the pricing page to whichever hero CTA sent them.\n * usePageGoal('pricing_view', { componentId: 'hero_cta' });\n *\n * @example\n * // Session-level only — no component to attribute it to.\n * usePageGoal('docs_view');\n */\nexport function usePageGoal(goalName: string, opts: PageGoalOptions = {}): void {\n const { componentId, ...goalOpts } = opts;\n const client = useSentient();\n // Called unconditionally (rules of hooks); only used when componentId is set.\n // It carries the dev-override contract — a forced variant records nothing —\n // so component-attributed arrivals inherit it for free.\n const fireComponentGoal = useAdaptiveGoal(componentId ?? '');\n const fired = useRef(false);\n // Callers pass an object literal, so `goalOpts` has a new identity every\n // render. Keeping it in a ref keeps it out of the dep array without making\n // the effect re-run (the latch would ignore it anyway).\n const optsRef = useRef(goalOpts);\n optsRef.current = goalOpts;\n\n useEffect(() => {\n if (!client || fired.current) return;\n fired.current = true;\n const { metadata, reward, value, currency, externalId } = optsRef.current;\n if (componentId) {\n fireComponentGoal(goalName, optsRef.current);\n return;\n }\n client.goal(goalName, {\n metadata: metadata ?? {},\n weight: reward ?? 1.0,\n stepIndex: 0,\n ...(value !== undefined ? { value } : {}),\n ...(currency !== undefined ? { currency } : {}),\n ...(externalId !== undefined ? { externalId } : {}),\n });\n }, [client, componentId, goalName, fireComponentGoal]);\n}\n","import { renderPrePaintScript } from '@sentientui/core';\nimport { confidenceBand } from '@sentientui/policy';\n\nexport type SentientPersonaScriptProps = {\n /** Publishable API key — selects the localStorage snapshot in the fallback path. */\n apiKey: string;\n /**\n * CSP nonce for the inline pre-paint script. Pass the same nonce your\n * `Content-Security-Policy` `script-src` allows (e.g. from Next.js middleware).\n * Required for strict CSP deployments that block `'unsafe-inline'`.\n */\n nonce?: string;\n /**\n * SSR-decided persona (from `loadAdaptiveDecision`). When present the\n * script embeds the literal values; when absent it reads the local\n * decision snapshot (SPA / return-visit path).\n */\n persona?: { persona: string; confidence: number } | null;\n};\n\n/** JSON string literal that is also safe inside an inline <script> element. */\nfunction inlineJsString(value: string): string {\n return JSON.stringify(value).replace(/</g, '\\\\u003c');\n}\n\n/** Exported for tests. Builds the inline JS (concatenation only — no backticks). */\nexport function personaScriptBody(props: SentientPersonaScriptProps): string {\n if (props.persona) {\n return (\n '(function(){try{var d=document.documentElement;' +\n 'if(d.hasAttribute(\"data-sentient-persona\"))return;' +\n 'd.setAttribute(\"data-sentient-persona\",' + inlineJsString(props.persona.persona) + ');' +\n 'd.setAttribute(\"data-sentient-confidence\",' + inlineJsString(confidenceBand(props.persona.confidence)) + ');' +\n '}catch(e){}})();'\n );\n }\n return renderPrePaintScript(props.apiKey);\n}\n\n/**\n * Single writer of the Rung-1a `<html>` attributes\n * (`data-sentient-persona`, `data-sentient-confidence`), executed pre-paint.\n *\n * `AdaptiveRoot` renders this automatically as its first child. For Pages\n * Router / Remix, render it yourself in `_document` / the root layout.\n *\n * IMPORTANT (install docs): add `suppressHydrationWarning` to your `<html>`\n * element — this script mutates documentElement before React hydrates it\n * (the same pattern next-themes uses). The client SDK adopts the attributes\n * as truth and never rewrites them mid-session.\n */\nexport function SentientPersonaScript(props: SentientPersonaScriptProps): JSX.Element {\n return (\n <script\n data-sentient-persona-script=\"\"\n nonce={props.nonce}\n dangerouslySetInnerHTML={{ __html: personaScriptBody(props) }}\n />\n );\n}\n","import { useEffect, useMemo, useRef } from 'react';\nimport type { SlotDeclInput } from '@sentientui/core';\nimport { validateSlotDecl } from '@sentientui/policy';\nimport { useAdaptiveApiKey, useSentient } from './provider.js';\nimport { useSlotResult } from './use-slot-result.js';\nimport { registerSlot } from './devtools-registry.js';\nimport {\n attachGoalListeners,\n goalLabelOf,\n goalValueOf,\n isDevBuild,\n normalizeGoal,\n trackExposure,\n type GoalConfig,\n} from './adaptive-shared.js';\n\nexport type UseAdaptiveTokensOptions = { goal?: string | GoalConfig };\nexport type UseAdaptiveTokensResult = {\n tokens: Record<string, string>;\n /** Spread on the slot's element: `data-<dim>` per dim + `data-sentient-slot`. */\n props: Record<string, string>;\n};\n\n// Warn once per slot id per page lifetime — not per render.\nconst warnedTokenSlots = new Set<string>();\n\nfunction cssEscape(value: string): string {\n if (typeof CSS !== 'undefined' && typeof CSS.escape === 'function') return CSS.escape(value);\n // Fallback for environments without CSS.escape: the value is interpolated\n // inside a double-quoted attribute selector (`[data-sentient-slot=\"…\"]`), so\n // both the backslash and the closing quote must be escaped — the old\n // quote-only escape let a slot id containing `\\` break out of the selector\n // (and an unescaped `\"` in a since-fixed path could match the wrong node).\n return value.replace(/[\\\\\"]/g, '\\\\$&');\n}\n\n/**\n * Rung 1b — adaptive design tokens. Declares a bounded token space; the\n * optimizer picks per persona; values apply as element-scoped data\n * attributes so they serialize through SSR markup (zero flicker,\n * hydration-safe). First value of each dim = baseline.\n *\n * ```tsx\n * const t = useAdaptiveTokens('hero', { tone: ['calm', 'urgent'] });\n * return <section {...t.props} className=\"hero\">…</section>;\n * // CSS: .hero[data-tone=\"urgent\"] .cta { … }\n * ```\n */\nexport function useAdaptiveTokens(\n id: string,\n dims: Record<string, readonly string[]>,\n opts?: UseAdaptiveTokensOptions,\n): UseAdaptiveTokensResult {\n const client = useSentient();\n const apiKey = useAdaptiveApiKey();\n\n // Freeze the declaration on the DIMS SIGNATURE, not the object identity: an\n // inline `dims={{...}}` literal is a fresh object each render, so keying on it\n // would churn a new decl every commit. A stringified signature is stable\n // across renders for the same dims yet updates if the declared space changes\n // (same convention as <Adaptive> / useAdaptive / AdaptiveGroup). A slot's\n // declared space is normally fixed for the session.\n const dimsKey = JSON.stringify(dims);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n const decl = useMemo<SlotDeclInput>(() => ({ id, dims }), [id, dimsKey]);\n const { result, arm, source } = useSlotResult(id, decl);\n const tokens = useMemo<Record<string, string>>(\n () => (typeof result === 'string' ? {} : result),\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [arm],\n );\n\n if (isDevBuild() && !warnedTokenSlots.has(id)) {\n const validity = validateSlotDecl({\n id,\n dims: Object.fromEntries(Object.entries(dims).map(([k, v]) => [k, [...v]])),\n });\n const space = Object.values(dims).reduce((n, values) => n * values.length, 1);\n if (!validity.ok) {\n warnedTokenSlots.add(id);\n console.warn(\n `[sentient] useAdaptiveTokens(\"${id}\"): invalid declaration — ${validity.reason}. Serving baseline.`,\n );\n } else if (space > 4) {\n warnedTokenSlots.add(id);\n console.warn(\n `[sentient] useAdaptiveTokens(\"${id}\") declares ${space} combinations — more than the recommended 4. Each extra combination needs more traffic to learn; consider fewer dims/values.`,\n );\n }\n }\n\n const goalKey =\n opts?.goal === undefined ? null : typeof opts.goal === 'string' ? opts.goal : JSON.stringify(opts.goal);\n\n // Devtools slot registry — the declared dims space drives both persona\n // simulation and the panel's per-dim override buttons. A slot is NOT a\n // component: registering it as one produced buttons that wrote the wrong\n // override channel (`__sentient_overrides` instead of `__sentient_slot_overrides`).\n // eslint-disable-next-line react-hooks/exhaustive-deps\n useEffect(() => registerSlot({ id, dims }), [id]);\n\n // Exposure — the slot equivalent of <Adaptive>'s variant_assigned event,\n // once per (slot, arm). variantId = canonical arm string.\n const exposedArmRef = useRef<string | null>(null);\n useEffect(() => {\n // Don't expose an unresolved baseline: a `baseline` source means the slot\n // was never decided (interim local decide, or a keyed client with no SSR\n // preload). Recording it accrues a phantom baseline impression that can\n // never convert. Once a real arm resolves (source flips to preloaded/\n // client) the exposure fires for that arm.\n // A forced arm (`override`, from devtools/tests) is a preview, not a real\n // exposure — recording it would train the optimizer on the override, the\n // same \"no events, weights unchanged\" contract <Adaptive> honors for\n // component overrides.\n if (!client || source === 'baseline' || source === 'override' || exposedArmRef.current === arm) return;\n exposedArmRef.current = arm;\n trackExposure(client, apiKey, id, arm);\n }, [client, apiKey, id, arm, source]);\n\n // Optional goal: the returned props carry data-sentient-slot, so the slot's\n // element is findable without a ref (the pinned return type has no ref).\n // Credit flows through componentGoal(slot id) — the core resolves the\n // attributed arm from its slot state (Task 3.3 fallback).\n useEffect(() => {\n // Forced arms record nothing (preview only) — same gate as the exposure.\n if (!client || !opts?.goal || source === 'override') return;\n const node = document.querySelector(`[data-sentient-slot=\"${cssEscape(id)}\"]`);\n if (!node) {\n if (isDevBuild()) {\n console.warn(\n `[sentient] useAdaptiveTokens(\"${id}\"): a goal is declared but no element carries the returned props — spread {...props} on the slot's element.`,\n );\n }\n return;\n }\n const label = goalLabelOf(opts.goal);\n const declaredValue = goalValueOf(opts.goal);\n let fired = false;\n return attachGoalListeners(node, normalizeGoal(opts.goal), {\n fireGoal: () => {\n if (fired) return;\n fired = true;\n // componentGoal credits the bandit (goal_achieved event, arm resolved\n // from slot state); goal() writes the session-level conversion funnel\n // record — exactly what <Adaptive> does for component goals. Slots\n // fired only the former, so slot conversions were invisible in the\n // goal funnel; fire both so membership matches components. (One funnel\n // record per conversion — see useAdaptiveGoal; keep labels unique.)\n // A static goal-config value rides on both writes (spec §5).\n if (declaredValue !== undefined) client.componentGoal(id, label, { value: declaredValue });\n else client.componentGoal(id, label);\n client.goal(label, {\n metadata: { componentId: id, arm },\n weight: 1.0,\n stepIndex: 0,\n ...(declaredValue !== undefined ? { value: declaredValue } : {}),\n });\n },\n fireStep: (name, weight, stepIndex) => {\n client.componentGoal(id, name, { reward: weight });\n client.goal(name, { metadata: { componentId: id, arm }, weight, stepIndex });\n },\n });\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [client, id, goalKey, arm, source]);\n\n const props = useMemo(() => {\n const p: Record<string, string> = { 'data-sentient-slot': id };\n for (const [dim, value] of Object.entries(tokens)) p[`data-${dim}`] = value;\n return p;\n }, [id, tokens]);\n\n return { tokens, props };\n}\n","import { useEffect, useReducer, useState, useSyncExternalStore } from 'react';\nimport { armOfResult, baselineResultFor, type SlotDeclInput, type SlotResult } from '@sentientui/core';\nimport { confidenceBand } from '@sentientui/policy';\nimport { useInitialPersona, useInitialSlots, useSentient } from './provider.js';\nimport { subscribeOverridesChanged, getOverridesVersion } from './override-events.js';\nimport { isDevBuild } from './adaptive-shared.js';\n\n// Warn once per slot id per page lifetime, not per render.\nconst warnedBaselineSlots = new Set<string>();\n\ndeclare global {\n interface Window {\n /** Test/devtools forcing: slot id → forced result (applyScenario sets this). */\n __sentient_slot_overrides?: Record<string, SlotResult>;\n /** Test/devtools forcing: forced persona (applyScenario sets this). */\n __sentient_persona_override?: { persona: string; confidence?: number };\n }\n}\n\nexport type SlotResolution = {\n result: SlotResult;\n /** Canonical arm string (`dim=value|…` for dims slots, arm id for arms slots). */\n arm: string;\n source: 'override' | 'preloaded' | 'client' | 'baseline';\n};\n\n/**\n * Internal. Resolves what a slot serves this render, synchronously:\n * test/devtools override → SSR-preloaded result → core client state\n * (decide cache, snapshot seed, failure baseline) → declared baseline.\n * Purely read-side: exposure/goal wiring belongs to the calling hook.\n */\nexport function useSlotResult(slotId: string, decl: SlotDeclInput): SlotResolution {\n // Re-render when devtools writes window.__sentient_slot_overrides.\n useSyncExternalStore(subscribeOverridesChanged, getOverridesVersion, () => 0);\n const client = useSentient();\n const initialSlots = useInitialSlots();\n const [, bump] = useReducer((n: number) => n + 1, 0);\n\n const override =\n typeof window !== 'undefined' ? window.__sentient_slot_overrides?.[slotId] : undefined;\n const preloaded = override === undefined ? initialSlots[slotId] : undefined;\n const fromClient =\n override === undefined && preloaded === undefined && client\n ? client.getSlotResult(slotId)\n : null;\n\n // Keyless local mode on a CSR-only page: nothing has decided this slot yet\n // (no SSR preload, no snapshot), so ask the local engine — zero network,\n // deterministic — and re-render when the decision lands. Keyed clients\n // never take this path: their slots decide server-side (SSR preload).\n const needsLocalDecide =\n client?.isLocal === true &&\n override === undefined &&\n preloaded === undefined &&\n fromClient === null;\n useEffect(() => {\n if (!needsLocalDecide || !client) return;\n let cancelled = false;\n void client.decide({ slots: [decl] }).then((outcome) => {\n if (!cancelled && outcome) bump();\n });\n return () => {\n cancelled = true;\n };\n // decl identity is fixed per slot id (callers memoize it on id).\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [client, slotId, needsLocalDecide]);\n\n const resolution: SlotResolution = (() => {\n if (override !== undefined) {\n return { result: override, arm: armOfResult(override), source: 'override' };\n }\n if (preloaded !== undefined) {\n return { result: preloaded, arm: armOfResult(preloaded), source: 'preloaded' };\n }\n if (fromClient !== null) {\n return { result: fromClient, arm: armOfResult(fromClient), source: 'client' };\n }\n const baseline = baselineResultFor(decl);\n return { result: baseline, arm: armOfResult(baseline), source: 'baseline' };\n })();\n\n // Dev-only: a live KEYED client that has settled on the declared baseline was\n // never decided — keyed clients decide slots server-side (SSR preload), and\n // (unlike local mode) issue no client-side decide, so this slot serves\n // baseline for the whole session and cannot learn. Callers gate exposure on\n // `source !== 'baseline'` so no phantom baseline impression is recorded; warn\n // once so the integrator preloads the decision. (Local mode's baseline is a\n // transient first paint before its decide resolves — excluded here.)\n useEffect(() => {\n if (!isDevBuild()) return;\n if (!client || client.isLocal === true) return;\n if (resolution.source !== 'baseline') return;\n if (warnedBaselineSlots.has(slotId)) return;\n warnedBaselineSlots.add(slotId);\n console.warn(\n `[sentient] slot \"${slotId}\" resolved to its baseline — no SSR-preloaded or decided result. ` +\n `Keyed clients decide slots server-side, so this slot serves baseline for the whole session ` +\n `and records no exposure. Preload it via loadAdaptiveDecision()/initialSlots so it can serve a decided arm and learn.`,\n );\n }, [client, resolution.source, slotId]);\n\n return resolution;\n}\n\n/**\n * Reads a forced persona: `window.__sentient_persona_override` (the devtools\n * panel, `applyScenario`, the Playwright/Cypress helpers) or the\n * `?sentient_persona=<PersonaKey>` URL param (mirrors `?sentient_variant=`).\n * Read POST-MOUNT only — it touches `window.location`.\n */\nfunction getPersonaOverride(): { persona: string; confidence: number } | null {\n if (typeof window === 'undefined') return null;\n const forced = window.__sentient_persona_override;\n if (forced?.persona) return { persona: forced.persona, confidence: forced.confidence ?? 1 };\n try {\n const value = new URLSearchParams(window.location.search).get('sentient_persona');\n if (value) return { persona: value, confidence: 1 };\n } catch {\n /* non-browser env */\n }\n return null;\n}\n\nexport type AdaptivePersona = {\n persona: string;\n confidence: number;\n band: 'low' | 'medium' | 'high';\n};\n\n/**\n * The current persona estimate for React consumers, resolved in priority\n * order: a forced override (devtools / `applyScenario` / `?sentient_persona=`)\n * → the SSR-provided `initialPersona` → the live client estimate (adopted\n * attributes / snapshot / decide). Returns `null` when nothing is known yet.\n *\n * Hydration-safe: the first render (server + pre-hydration client) uses ONLY\n * the SSR-provided persona so server and client agree; the override channel and\n * the live client estimate — neither visible to the server — are read after\n * mount. Re-renders when a persona/variant override is written, so devtools or\n * a test forcing a persona mid-session takes effect immediately.\n */\nexport function useAdaptivePersona(): AdaptivePersona | null {\n const client = useSentient();\n const initialPersona = useInitialPersona();\n // Re-render when the override channel is written. NOTE: unlike useAssignment /\n // AdaptiveText — which fold the override into the useSyncExternalStore snapshot\n // (getDevOverride returns a STABLE string) — persona can't: getPersonaOverride\n // allocates a fresh object each call, which would fail the snapshot's Object.is\n // check and trip React's \"getSnapshot should be cached\" loop guard. So we\n // subscribe to the stable version counter for reactivity and read the override\n // in the render body (behind a mounted gate). That one-frame post-mount flip is\n // harmless here because this hook is side-effect-free (no assign/exposure to\n // leak), which is exactly why useAssignment/AdaptiveText could NOT tolerate it.\n useSyncExternalStore(subscribeOverridesChanged, getOverridesVersion, () => 0);\n const [mounted, setMounted] = useState(false);\n useEffect(() => setMounted(true), []);\n\n const withBand = (p: { persona: string; confidence: number }): AdaptivePersona => ({\n persona: p.persona,\n confidence: p.confidence,\n band: confidenceBand(p.confidence),\n });\n\n // First render must match the server, which can see neither window nor the\n // client estimate — use only initialPersona to avoid a hydration mismatch on\n // a ?sentient_persona= page.\n if (!mounted) {\n return initialPersona ? withBand(initialPersona) : null;\n }\n const override = getPersonaOverride();\n if (override) return withBand(override);\n if (initialPersona) return withBand(initialPersona);\n const live = client ? client.getPersona() : null;\n return live ? withBand(live) : null;\n}\n","import { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport { attachMicroSignalDetectors, type ComponentGoalOptions } from '@sentientui/core';\nimport { useAdaptiveApiKey, useSentient } from './provider.js';\nimport { useAssignment } from './use-assignment.js';\nimport { registerComponent } from './devtools-registry.js';\nimport {\n attachGoalListeners,\n goalLabelOf,\n goalValueOf,\n isDevBuild,\n normalizeGoal,\n trackExposure,\n type GoalConfig,\n} from './adaptive-shared.js';\n\nexport type UseAdaptiveBind = {\n ref: (el: HTMLElement | null) => void;\n 'data-sentient-id': string;\n 'data-sentient-variant': string;\n};\n\nexport type UseAdaptiveResult<T> = {\n variant: string;\n value: T;\n /** Spread on the rendered element — wires exposure, goal listeners, and micro-signals. */\n bind: UseAdaptiveBind;\n fireGoal: (goalType?: string, opts?: ComponentGoalOptions) => void;\n};\n\nconst warnedUnbound = new Set<string>();\n\n/**\n * Rung 2 — headless, measurement-complete variant swap. Supersedes\n * `useAssignment` (which selects a variant but wires no measurement).\n *\n * `goal` is REQUIRED: without one the optimizer accumulates exposures with\n * zero rewards and cannot learn. `bind` MUST be attached to the rendered\n * element — dev mode warns loudly when a slot renders unbound.\n *\n * ```tsx\n * const { value, bind } = useAdaptive('buy-box', {\n * variants: { calm: <CalmBuyBox/>, urgent: <UrgentBuyBox/> }, // first key = baseline\n * goal: 'buy_click',\n * });\n * return <div {...bind}>{value}</div>;\n * ```\n */\nexport function useAdaptive<T>(\n id: string,\n config: { variants: Record<string, T>; goal: string | GoalConfig },\n): UseAdaptiveResult<T> {\n if (isDevBuild() && !config.goal) {\n throw new Error(\n `[sentient] useAdaptive(\"${id}\"): a goal is required — without one the optimizer accumulates exposures with no rewards and cannot learn. Pass e.g. goal: 'buy_click'.`,\n );\n }\n\n const client = useSentient();\n const apiKey = useAdaptiveApiKey();\n // Freeze the variant-id array on the KEY SET (same convention as <Adaptive> /\n // AdaptiveGroup / useAdaptiveTokens): stable across renders for the same keys\n // yet updates if the declared set changes. Declared space is normally fixed\n // per slot id for a session.\n const variantKey = Object.keys(config.variants).join(' ');\n // eslint-disable-next-line react-hooks/exhaustive-deps\n const variantIds = useMemo(() => Object.keys(config.variants), [variantKey]);\n const { variantId, isOverride, settled } = useAssignment(id, variantIds);\n const variant = variantId ?? variantIds[0] ?? '';\n const value = config.variants[variant] as T;\n\n const [node, setNode] = useState<HTMLElement | null>(null);\n const nodeRef = useRef<HTMLElement | null>(null);\n const ref = useCallback((el: HTMLElement | null) => {\n nodeRef.current = el;\n setNode(el);\n }, []);\n\n const goalKey = typeof config.goal === 'string' ? config.goal : JSON.stringify(config.goal);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n const goal = useMemo(() => normalizeGoal(config.goal), [goalKey]);\n const goalLabel = goalLabelOf(config.goal);\n\n useEffect(() => registerComponent({ id, variantIds, goal: goalLabel }), [id, variantIds, goalLabel]);\n\n // Exposure — same variant_assigned mechanics as <Adaptive>, fired once per\n // (id, variant) once the bind target is in the DOM.\n const exposedRef = useRef<string | null>(null);\n useEffect(() => {\n // Forced variants are a dev/test view — no exposure, no goals, no\n // micro-signals may be recorded (same gate as <Adaptive>).\n if (isOverride) return;\n // Only the SETTLED assignment is a real exposure; the interim variantIds[0]\n // placeholder shown while assign() is in flight must not accrue a phantom\n // baseline impression (same gate as <Adaptive>).\n if (!settled) return;\n if (!client || !variant || !node) return;\n if (exposedRef.current === variant) return;\n exposedRef.current = variant;\n trackExposure(client, apiKey, id, variant);\n }, [client, apiKey, id, variant, node, isOverride, settled]);\n\n // Goal listeners — identical machinery to <Adaptive> (shared helper).\n const goalFiredRef = useRef(false);\n useEffect(() => {\n goalFiredRef.current = false;\n }, [variant, goalKey]);\n useEffect(() => {\n if (isOverride) return;\n if (!client || !variant || !node) return;\n // A static goal-config value rides on both writes (spec §5); steps carry\n // weights, never values (spec §9.4).\n const declaredValue = goalValueOf(goal);\n return attachGoalListeners(node, goal, {\n fireGoal: () => {\n if (goalFiredRef.current) return;\n goalFiredRef.current = true;\n client.track({\n projectId: apiKey,\n componentId: id,\n variantId: variant,\n eventType: 'goal_achieved',\n goalType: goalLabel,\n payload: { reward: 1.0, ...(declaredValue !== undefined ? { goalValue: declaredValue } : {}) },\n });\n client.goal(goalLabel, {\n metadata: { componentId: id, variantId: variant },\n weight: 1.0,\n stepIndex: 0,\n ...(declaredValue !== undefined ? { value: declaredValue } : {}),\n });\n },\n fireStep: (name, weight, stepIndex) => {\n client.track({\n projectId: apiKey,\n componentId: id,\n variantId: variant,\n eventType: 'goal_achieved',\n goalType: name,\n payload: { reward: weight },\n });\n client.goal(name, { metadata: {}, weight, stepIndex });\n },\n });\n }, [client, node, variant, apiKey, id, goal, goalLabel, isOverride]);\n\n // Micro-signal detectors — the third thing <Adaptive>'s container wires.\n useEffect(() => {\n if (isOverride) return;\n if (!client || !variant || !node) return;\n const assignedAt = Date.now();\n return attachMicroSignalDetectors(\n (signalType, extra = {}) => {\n client.track({\n projectId: apiKey,\n componentId: id,\n variantId: variant,\n eventType: 'micro_signal',\n payload: { signalType, ...extra },\n });\n },\n node,\n assignedAt,\n );\n }, [client, node, variant, apiKey, id, isOverride]);\n\n // Dev warning: bind never attached shortly after mount → exposures would\n // never fire and the slot cannot learn. Once per slot id.\n useEffect(() => {\n if (!isDevBuild()) return;\n if (!client) return;\n const timer = setTimeout(() => {\n if (!nodeRef.current && !warnedUnbound.has(id)) {\n warnedUnbound.add(id);\n console.warn(\n `[sentient] useAdaptive(\"${id}\"): bind was never attached — spread {...bind} on the rendered element, otherwise exposure and goal tracking cannot work and the optimizer learns nothing.`,\n );\n }\n }, 0);\n return () => clearTimeout(timer);\n }, [client, id]);\n\n const fireGoal = useCallback(\n (goalType?: string, opts?: ComponentGoalOptions) => {\n if (isOverride) return; // forced variants record nothing, even manual goals\n // componentGoal credits the bandit; goal() writes the session goal-funnel\n // record. The declared-goal listener above fires both, so a manual goal\n // for the same slot must too (otherwise it's absent from the funnel).\n // Like useAdaptiveGoal, this writes one funnel record per call with no\n // cross-call latch — keep goal labels unique per conversion (a component\n // that ALSO fires a declared goal on the same action records both).\n const name = goalType ?? goalLabel;\n client?.componentGoal(id, name, opts);\n client?.goal(name, {\n metadata: opts?.metadata ?? {},\n weight: opts?.reward ?? 1.0,\n stepIndex: 0,\n ...(opts?.value !== undefined ? { value: opts.value } : {}),\n ...(opts?.currency !== undefined ? { currency: opts.currency } : {}),\n ...(opts?.externalId !== undefined ? { externalId: opts.externalId } : {}),\n });\n },\n [client, id, goalLabel, isOverride],\n );\n\n const bind = useMemo<UseAdaptiveBind>(\n () => ({ ref, 'data-sentient-id': id, 'data-sentient-variant': variant }),\n [ref, id, variant],\n );\n\n return { variant, value, bind, fireGoal };\n}\n","import { Children, isValidElement, useEffect, useMemo, useRef, type ReactNode } from 'react';\nimport type { SlotDeclInput } from '@sentientui/core';\nimport { useAdaptiveApiKey, useSentient } from './provider.js';\nimport { useSlotResult } from './use-slot-result.js';\nimport { registerSlot } from './devtools-registry.js';\nimport {\n attachGoalListeners,\n goalLabelOf,\n goalValueOf,\n isDevBuild,\n normalizeGoal,\n trackExposure,\n type GoalConfig,\n} from './adaptive-shared.js';\n\nexport type AdaptiveGroupProps = {\n id: string;\n /** Arrangement id → ordered child keys. FIRST key = baseline default. */\n arrangements: Record<string, string[]>;\n /** Explicit baseline arrangement id (defaults to the first declared). */\n baseline?: string;\n /** Optional slot-scoped goal — credited via componentGoal(group id). */\n goal?: string | GoalConfig;\n /** Keyed children — every key referenced by an arrangement must exist. */\n children: ReactNode;\n};\n\n// Warn once per group id per page lifetime.\nconst warnedGroups = new Set<string>();\n\n/**\n * Rung 3 — bounded mini-layout. Reorders KEYED children into the decided\n * arrangement (enumerated-arms slot: arms = Object.keys(arrangements)).\n * Declared orders only — never free permutation, never show/hide.\n * Fail-safe: unknown arrangement or key mismatch renders declaration order.\n */\nexport function AdaptiveGroup(props: AdaptiveGroupProps): JSX.Element {\n const client = useSentient();\n const apiKey = useAdaptiveApiKey();\n const containerRef = useRef<HTMLDivElement>(null);\n\n // Freeze the arrangement-id array on the KEY SET (same convention as\n // <Adaptive> / useAdaptive / useAdaptiveTokens): stable across renders for the\n // same keys yet updates if the declared set changes. Declared space is\n // normally fixed per group id for a session.\n const arrangementKey = Object.keys(props.arrangements).join(' ');\n // eslint-disable-next-line react-hooks/exhaustive-deps\n const arrangementIds = useMemo(() => Object.keys(props.arrangements), [arrangementKey]);\n const decl = useMemo<SlotDeclInput>(\n () => ({\n id: props.id,\n arms: arrangementIds,\n ...(props.baseline !== undefined ? { baseline: props.baseline } : {}),\n }),\n [props.id, arrangementIds, props.baseline],\n );\n const { arm, source } = useSlotResult(props.id, decl);\n\n if (\n isDevBuild() &&\n props.baseline !== undefined &&\n props.baseline !== arrangementIds[0] &&\n !warnedGroups.has(props.id + ':baseline')\n ) {\n warnedGroups.add(props.id + ':baseline');\n console.warn(\n `[sentient] <AdaptiveGroup id=\"${props.id}\">: baseline \"${props.baseline}\" is not the first-declared arrangement (\"${arrangementIds[0]}\"). The first arrangement should usually be the page's real incumbent (the holdout sees it).`,\n );\n }\n\n const childArray = Children.toArray(props.children).filter(isValidElement);\n const byKey = new Map<string, (typeof childArray)[number]>();\n for (const child of childArray) {\n // Children.toArray prefixes explicit keys with '.$'.\n byKey.set(String(child.key ?? '').replace(/^\\.\\$/, ''), child);\n }\n\n const order = props.arrangements[arm];\n const canReorder =\n order !== undefined &&\n order.length === childArray.length &&\n order.every((key) => byKey.has(key));\n\n if (\n isDevBuild() &&\n order !== undefined &&\n !canReorder &&\n !warnedGroups.has(props.id + ':keys')\n ) {\n warnedGroups.add(props.id + ':keys');\n console.warn(\n `[sentient] <AdaptiveGroup id=\"${props.id}\">: arrangement \"${arm}\" [${order.join(', ')}] does not match the children's keys — rendering declaration order (fail-safe).`,\n );\n }\n\n const ordered = canReorder ? order.map((key) => byKey.get(key)!) : childArray;\n\n // Devtools slot registry — the declared arms space drives persona simulation\n // and the panel's per-arm override buttons. A group is a slot, not a component:\n // registering it as one produced buttons that wrote the wrong override channel.\n useEffect(\n () => registerSlot({ id: props.id, arms: Object.keys(props.arrangements) }),\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [props.id],\n );\n\n // Exposure — once per (group, arrangement). An unresolved `baseline` source\n // means the group was never decided (interim local decide, or a keyed client\n // with no SSR preload); exposing it would record a phantom baseline\n // impression that can never convert, so skip until a real arm resolves.\n const exposedArmRef = useRef<string | null>(null);\n useEffect(() => {\n // A forced arm (`override`, from devtools/tests) is a preview, not a real\n // exposure — skip it so the optimizer isn't trained on the override (same\n // contract <Adaptive> honors for component overrides).\n if (!client || source === 'baseline' || source === 'override' || exposedArmRef.current === arm) return;\n exposedArmRef.current = arm;\n trackExposure(client, apiKey, props.id, arm);\n }, [client, apiKey, props.id, arm, source]);\n\n // Optional goal — slot-scoped credit through componentGoal (the core\n // resolves the attributed arm from its slot state; see Task 3.3).\n const goalKey =\n props.goal === undefined ? null : typeof props.goal === 'string' ? props.goal : JSON.stringify(props.goal);\n useEffect(() => {\n // Forced arms record nothing (preview only) — same gate as the exposure.\n if (!client || props.goal === undefined || source === 'override') return;\n const node = containerRef.current;\n if (!node) return;\n const label = goalLabelOf(props.goal);\n const declaredValue = goalValueOf(props.goal);\n let fired = false;\n return attachGoalListeners(node, normalizeGoal(props.goal), {\n fireGoal: () => {\n if (fired) return;\n fired = true;\n // componentGoal credits the bandit; goal() writes the session-level\n // conversion funnel record — matching <Adaptive>. Firing only the\n // former left group conversions out of the goal funnel. A static\n // goal-config value rides on both writes (spec §5).\n if (declaredValue !== undefined) client.componentGoal(props.id, label, { value: declaredValue });\n else client.componentGoal(props.id, label);\n client.goal(label, {\n metadata: { componentId: props.id, arm },\n weight: 1.0,\n stepIndex: 0,\n ...(declaredValue !== undefined ? { value: declaredValue } : {}),\n });\n },\n fireStep: (name, weight, stepIndex) => {\n client.componentGoal(props.id, name, { reward: weight });\n client.goal(name, { metadata: { componentId: props.id, arm }, weight, stepIndex });\n },\n });\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [client, props.id, goalKey, arm, source]);\n\n return (\n <div ref={containerRef} data-sentient-id={props.id} data-sentient-variant={arm}>\n {ordered}\n </div>\n );\n}\n","/** @deprecated Use `useSessionSegment()` from the provider, or `deriveSessionSegment` from `@sentientui/core`. */\nexport { deriveSessionSegment as detectSegment } from '@sentientui/core';\n","/**\n * Agent-readable content feed. Merges SDK-known data (winning variants, layout\n * order) with developer-supplied page content, and renders it either as a\n * server-rendered inline JSON-LD block (read by passive AI crawlers, which do\n * not run JS) or as Markdown (for agents that content-negotiate `text/markdown`).\n *\n * No React or DOM APIs — safe to import in server components, route handlers,\n * and middleware.\n */\n\nexport type AgentBlock = {\n /** Component ID. */\n id: string;\n /** Winning variant ID currently served. */\n variant: string;\n /** Agent-readable data attached to the served variant, if any. */\n content?: unknown;\n};\n\nexport type AgentFeed = {\n page: string;\n title?: string;\n summary?: string;\n layoutOrder?: string[];\n blocks: AgentBlock[];\n /** Developer-supplied extra fields (products, specs, arbitrary JSON). */\n [key: string]: unknown;\n};\n\n/** Fields the SDK owns — developer content can never overwrite these. */\nconst RESERVED_FIELDS = ['page', 'blocks', 'layoutOrder'] as const;\n\nconst registry = new Map<string, Record<string, unknown>>();\n\n/**\n * Register page-level structured content the SDK can't infer (title, summary,\n * product fields, arbitrary JSON), keyed by page path. Call at module load.\n */\nexport function defineAgentContent(page: string, content: Record<string, unknown>): void {\n registry.set(page, content);\n}\n\n/** Look up registered content for a page. */\nexport function getAgentContent(page: string): Record<string, unknown> | undefined {\n return registry.get(page);\n}\n\n/** Clear the registry — intended for tests. */\nexport function clearAgentContent(): void {\n registry.clear();\n}\n\n/**\n * Merge SDK-known data with developer-supplied content into a single feed.\n * Developer content fills in title/summary/etc. but can never overwrite the\n * SDK-authoritative fields (`page`, `blocks`, `layoutOrder`).\n */\nexport function buildAgentFeed(input: {\n page: string;\n blocks: AgentBlock[];\n layoutOrder?: string[];\n content?: Record<string, unknown>;\n}): AgentFeed {\n const supplied = input.content ?? getAgentContent(input.page) ?? {};\n const safe: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(supplied)) {\n if (!(RESERVED_FIELDS as readonly string[]).includes(k)) safe[k] = v;\n }\n const feed: AgentFeed = {\n ...safe,\n page: input.page,\n blocks: input.blocks,\n };\n if (input.layoutOrder) feed.layoutOrder = input.layoutOrder;\n return feed;\n}\n\n/**\n * Render the feed as a server-rendered inline JSON-LD `<script>` string. `<` is\n * escaped to `<` so embedded content cannot break out of the script\n * element. MUST be emitted on the server — passive crawlers never run client JS.\n */\nexport function renderAgentJsonLd(feed: AgentFeed): string {\n return `<script type=\"application/ld+json\">${renderAgentJsonLdBody(feed)}</script>`;\n}\n\n/**\n * The escaped JSON-LD body only (no `<script>` wrapper). For React server\n * components, inject via `<script type=\"application/ld+json\"\n * dangerouslySetInnerHTML={{ __html: renderAgentJsonLdBody(feed) }} />`.\n */\nexport function renderAgentJsonLdBody(feed: AgentFeed): string {\n return JSON.stringify({ '@context': 'https://schema.org', '@type': 'WebPage', ...feed })\n .replace(/</g, '\\\\u003c');\n}\n\n/** Render the feed as Markdown for agents that negotiate `text/markdown`. */\nexport function renderAgentMarkdown(feed: AgentFeed): string {\n const lines: string[] = [];\n if (feed.title) lines.push(`# ${feed.title}`, '');\n if (feed.summary) lines.push(String(feed.summary), '');\n\n for (const [k, v] of Object.entries(feed)) {\n if (['page', 'title', 'summary', 'blocks', 'layoutOrder'].includes(k)) continue;\n lines.push(`## ${k}`, '', '```json', JSON.stringify(v, null, 2), '```', '');\n }\n\n if (feed.blocks.length > 0) {\n lines.push('## blocks', '');\n for (const b of feed.blocks) {\n lines.push(`- **${b.id}** → variant \\`${b.variant}\\``);\n if (b.content !== undefined) {\n lines.push('', ' ```json', JSON.stringify(b.content, null, 2), ' ```');\n }\n }\n lines.push('');\n }\n\n return lines.join('\\n').trimEnd() + '\\n';\n}\n"],"mappings":"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","names":["src_exports","__export","Adaptive","AdaptiveGroup","AdaptiveProvider","AdaptiveText","SentientPersonaScript","buildAgentFeed","defineAgentContent","getAgentContent","renderAgentJsonLd","renderAgentJsonLdBody","renderAgentMarkdown","useAdaptive","useAdaptiveApiBaseUrl","useAdaptiveGoal","useAdaptivePersona","useAdaptiveTokens","useAssignment","useInitialAssignments","useLayoutOrder","usePageGoal","useSentient","__toCommonJS","import_react","import_core","store","listeners","subscribe","componentId","cb","set","update","weights","e","getWeights","_a","ssrFallback","state","w","getPreviewMode","state","subscribePreview","fn","listeners","createPreviewClient","inner","componentId","segment","variantIds","agentData","agentDataByVariant","slotId","EVENT","getOverridesVersion","_a","subscribeOverridesChanged","fn","EVENT","publishDevtoolsConfig","config","isDevBuild","_a","normalizeGoal","goal","goalLabelOf","goalValueOf","isClickableTarget","el","tag","findClickable","start","container","selector","cursor","e","attachGoalListeners","node","handlers","firedSteps","wcCleanups","sub","stepName","stepWeight","idx","fireStep","onClick","target","onSubmit","threshold","io","entries","entry","c","subgoals","remaining","_","i","checkComposite","cleanups","trackExposure","client","apiKey","componentId","variantId","ssrFallback","state","w","emit","fn","NOOP_UNREGISTER","registerComponent","c","isDevBuild","registerSlot","s","registerSections","sections","import_jsx_runtime","deriveDefaultSegment","_a","_b","device","source","e","DEFAULT_API_BASE_URL","AdaptiveContext","useConsentSource","granted","setGranted","sourceRef","cookie","value","event","hasCheck","read","s","want","c","onDecision","AdaptiveProvider","props","client","setClient","sessionSegment","previewOn","setPreviewOn","getPreviewMode","subscribePreview","sourceGranted","consent","prev","config","cancelled","created","stopEngagement","startEngagement","startEngagementCapture","initGraph","__spreadProps","__spreadValues","poll","entries","entry","weights","v","update","timerId","ssrFallback","apiBaseUrl","frozenConfigRef","current","key","publishDevtoolsConfig","decided","registerSections","exposedClient","createPreviewClient","_c","_d","_e","useSentient","useAdaptiveApiKey","useInitialAssignments","useSessionSegment","useSsrFallback","useOnAssignment","useDebug","useLayoutOrder","contextOrder","override","subscribeOverridesChanged","useInitialSlots","useInitialPersona","useAdaptiveApiBaseUrl","import_react","import_core","import_react","getDevOverride","componentId","_a","global","params","raw","sep","e","PRIOR_PULLS","pickFromWeights","weights","variantIds","_a","_b","best","v","pulls","score","useAssignment","componentId","agentData","agentDataByVariant","initialAssignments","useInitialAssignments","ssrFallback","useSsrFallback","client","useSentient","segment","useSessionSegment","onAssignment","useOnAssignment","debug","useDebug","assignmentReportedRef","devOverride","subscribeOverridesChanged","getDevOverride","overrideVariant","overrideLoggedRef","state","setState","preloaded","cached","getWeights","chosen","reportAssignment","variantId","prev","cancelled","result","subscribe","import_jsx_runtime","AdaptiveImpl","props","_a","client","useSentient","apiKey","useAdaptiveApiKey","variantKey","variantIds","variantId","content","isOverride","settled","useAssignment","containerRef","mounted","setMounted","goalFiredRef","microGoalFiredRef","assignTrackedRef","goalKey","goal","normalizeGoal","goalLabel","registerComponent","trackExposure","node","timerId","hoverStart","onEnter","onLeave","assignedAt","signalType","extra","_b","_c","__spreadValues","mapping","name","weight","stepIndex","declaredValue","goalValueOf","attachGoalListeners","jsxContent","managedContent","isDevBuild","Adaptive","prev","next","prevKeys","nextKeys","k","import_react","import_jsx_runtime","AdaptiveText","id","defaultText","Tag","className","goalProp","_a","client","useSentient","apiKey","useAdaptiveApiKey","onAssignment","useOnAssignment","segment","useSessionSegment","trackedRef","nodeRef","override","subscribeOverridesChanged","getDevOverride","text","setText","_b","variantId","setVariantId","cancelled","result","isDevBuild","goalKey","goal","normalizeGoal","goalLabel","goalFiredRef","node","declaredValue","goalValueOf","attachGoalListeners","__spreadValues","name","weight","stepIndex","displayText","cached","el","import_react","useAdaptiveGoal","componentId","client","useSentient","firedOnce","goalType","opts","_a","_b","getDevOverride","__spreadValues","import_react","usePageGoal","goalName","opts","_a","componentId","goalOpts","__objRest","client","useSentient","fireComponentGoal","useAdaptiveGoal","fired","optsRef","metadata","reward","value","currency","externalId","__spreadValues","import_core","import_policy","import_jsx_runtime","inlineJsString","value","personaScriptBody","props","SentientPersonaScript","import_react","import_policy","import_react","import_core","import_policy","warnedBaselineSlots","useSlotResult","slotId","decl","_a","subscribeOverridesChanged","getOverridesVersion","client","useSentient","initialSlots","useInitialSlots","bump","n","override","preloaded","fromClient","needsLocalDecide","cancelled","outcome","resolution","baseline","isDevBuild","getPersonaOverride","forced","value","e","useAdaptivePersona","initialPersona","useInitialPersona","mounted","setMounted","withBand","p","live","warnedTokenSlots","cssEscape","value","useAdaptiveTokens","id","dims","opts","client","useSentient","apiKey","useAdaptiveApiKey","dimsKey","decl","result","arm","source","useSlotResult","tokens","isDevBuild","validity","k","v","space","n","values","goalKey","registerSlot","exposedArmRef","trackExposure","node","label","goalLabelOf","declaredValue","goalValueOf","fired","attachGoalListeners","normalizeGoal","__spreadValues","name","weight","stepIndex","props","p","dim","import_react","import_core","warnedUnbound","useAdaptive","id","config","_a","isDevBuild","client","useSentient","apiKey","useAdaptiveApiKey","variantKey","variantIds","variantId","isOverride","settled","useAssignment","variant","value","node","setNode","nodeRef","ref","el","goalKey","goal","normalizeGoal","goalLabel","goalLabelOf","registerComponent","exposedRef","trackExposure","goalFiredRef","declaredValue","goalValueOf","attachGoalListeners","__spreadValues","name","weight","stepIndex","assignedAt","signalType","extra","timer","fireGoal","goalType","opts","_b","bind","import_react","import_jsx_runtime","warnedGroups","AdaptiveGroup","props","_a","client","useSentient","apiKey","useAdaptiveApiKey","containerRef","arrangementKey","arrangementIds","decl","__spreadValues","arm","source","useSlotResult","isDevBuild","childArray","byKey","child","order","canReorder","key","ordered","registerSlot","exposedArmRef","trackExposure","goalKey","node","label","goalLabelOf","declaredValue","goalValueOf","fired","attachGoalListeners","normalizeGoal","name","weight","stepIndex","import_core","RESERVED_FIELDS","registry","defineAgentContent","page","content","getAgentContent","buildAgentFeed","input","_a","_b","supplied","getAgentContent","safe","k","v","RESERVED_FIELDS","feed","__spreadProps","__spreadValues","renderAgentJsonLd","renderAgentJsonLdBody","renderAgentMarkdown","lines","b","import_core"]}