/** * Web shell boot — the library face consumed by the apps/web entry (api * contracts v3 §0.3/§9.3): root ctx → hold the loader machinery (statically * imported; the loader cannot load itself) → seed the module table → render * the AppRoot loading page → loader.start() → await settled() → flip the * settled signal so AppRoot switches to the real UI in one pass. Load * failures reject settled(); AppRoot stays on the loading page listing them * (fail loud). */ import { Context } from 'cordis' import { createRoot } from 'react-dom/client' import type { ReactNode } from 'react' import type { ObservableSnapshot } from '@deepseek-ai/dsh-client-runtime/client' import { createSlotRenderer } from '@deepseek-ai/dsh-client-web-react' import { createClientLoader, type ClientLoaderOptions } from '@deepseek-ai/dsh-client-runtime/loader' import { AppRoot } from './AppRoot.tsx' import { buildRenderApp } from './app.tsx' import { seedModules } from './seed.ts' import './base.css' /** Manually flipped settled signal (AppRoot's gate; see AppRootProps.settled). */ function settledSignal(): ObservableSnapshot & { flip: () => void } { let value = false const listeners = new Set<() => void>() return { getSnapshot: () => value, subscribe: (fn) => { listeners.add(fn); return () => { listeners.delete(fn) } }, flip: () => { value = true for (const fn of [...listeners]) fn() }, } } /** Loader transport seams the shell passes through (jsdom tests replace the