<!-- source-hash: d7ee3e1b5c0c5cbc9cc3e58aa144f151 -->
Resolves a React context value by preferring an outer provider's value when present, falling back to a memoized factory default when no outer provider exists.

## Key Components

### `useOuterOrDefault<T>(context, factory, deps)`

A generic hook that enables "outer-override" provider patterns used across hub and embedder providers.

| Parameter | Type | Description |
|-----------|------|-------------|
| `context` | `Context<T \| null>` | The React context to read from |
| `factory` | `() => T` | Produces the default value when no outer provider is mounted |
| `deps` | `ReadonlyArray<unknown>` | Memoization dependencies for `factory` (defaults to `[]`) |

**Returns:** The outer context value if available, otherwise the memoized factory result.

## Usage Example

```typescript
// Stable default (factory runs once — safe for constant/module-scope values)
const runtime = useOuterOrDefault(ChatRuntimeContext, () => createDefaultRuntime())

// Reactive default (factory re-runs when callbacks change)
const runtime = useOuterOrDefault(
  ChatRuntimeContext,
  () => createChatRuntime({ navigate, decideNewTab }),
  [navigate, decideNewTab], // must be stable refs (e.g. from useCallback)
)
```

## Key Behaviors

- **Tree shape stability** — the same provider element renders at the same position regardless of whether an outer provider is mounted, preventing unnecessary consumer remounts.
- **Reference stability** — returns the same object reference across renders to avoid breaking downstream `useMemo` consumers. With `deps: []` this is trivially guaranteed; with reactive deps, callers must stabilize deps via `useCallback`.
- **Outer wins** — if an embedder mounts a matching provider above the hub provider, that outer value takes precedence unconditionally.