# YINIAN Desktop M1 Handoff > Updated: 2026-04-26 > Scope: M1 foundation closure after ClawX fork adaptation. See `docs/PILOT_QA.md` for the current M2 pilot demo and QA gate. ## 1. What M1 Delivers M1 turns the ClawX fork into a YINIAN-ready desktop foundation without removing the original ClawX/OpenClaw capabilities. Delivered: - YINIAN login-first product flow. - Auth session restore and logout cleanup. - Hotel tenant context and hotel switching. - Config snapshot sync from mock or HTTP control plane. - Local skill registry grouped by `hotelId`. - Skills sync v0 from manifest to registry. - Today page as the new production home route. - Skills page replaced with YINIAN skill control surface. - Gateway auto-start deferred until YINIAN authentication. - Legacy ClawX E2E compatibility preserved. - Workspace packages added for future kernel/skill/UI boundaries. Not delivered in M1: - Real skill bundle download. - Signature verification and unpacking. - Real OTA skill execution. - Final backend API contract. - Customer-ready pilot dashboard depth. ## 2. Main Behavior ### Production Flow 1. App starts. 2. Renderer calls `window.yinian.auth.restoreSession()`. 3. If no valid session exists, user is redirected to `/login`. 4. Login succeeds through mock control plane by default, or HTTP mode when configured. 5. App loads config and local skill registry for the current hotel. 6. App navigates to `/today`. 7. Gateway initializes and starts only after authenticated hotel context exists. ### E2E Compatibility Flow When Electron is launched with `CLAWX_E2E=1`, main process appends `e2e=1` to the renderer URL. In E2E mode: - Legacy setup flow remains available. - `/` renders the original Chat page, not Today. - Default language is English unless the test changes it. - Gateway store is initialized after setup, but gateway is not auto-started. This keeps the inherited ClawX regression suite valid while production behavior moves to YINIAN. ## 3. Environment Switches | Variable | Values | Default | Purpose | |---|---|---:|---| | `YINIAN_API_BASE_URL` | URL | unset | Enables HTTP control plane. When unset, app uses mock mode. | | `CLAWX_LEGACY_AUTOSTART` | `1` / unset | unset | Restores old main-process gateway auto-start for debugging. Production YINIAN keeps gateway deferred until login. | | `CLAWX_E2E` | `1` / unset | unset | Enables E2E compatibility mode. Used by Playwright fixtures. | | `CLAWX_E2E_SKIP_SETUP` | `1` / unset | unset | Adds `e2eSkipSetup=1` for tests that bypass setup. | ## 4. Storage Boundary YINIAN uses a separate Electron store namespace: - Store name: `yinian` - Helper: `electron/yinian/storage.ts` Stored data: - `session`: persisted YINIAN session metadata. - `configs`: config snapshots keyed by hotel id. - `skillRegistryByHotel`: local skill registries keyed by hotel id. Important constraints: - Renderer never reads tokens directly. - Renderer accesses auth/config/skill data only through `window.yinian`. - Mock mode persists enough session data to restore the local demo. - HTTP mode keeps `accessToken` in memory and reserves persistence for `refreshToken`. - Logout clears session, current hotel config, and current hotel skill registry through the control plane. ## 5. Public Renderer API The preload exposes `window.yinian`: ```ts window.yinian.auth.restoreSession() window.yinian.auth.getSessionState() window.yinian.auth.loginWithSms(input) window.yinian.auth.loginWithPassword(input) window.yinian.auth.logout() window.yinian.app.getConfig() window.yinian.app.switchHotel(hotelId) window.yinian.skills.sync() window.yinian.skills.listLocal() window.yinian.skills.getRegistry(hotelId?) ``` Shared types live in `shared/yinian.ts`. ## 6. Module Inventory ### Electron Main - `electron/main/ipc/yinian.ts` - IPC handlers for auth, config, hotel switching, skill sync, and registry reads. - `electron/yinian/control-plane.ts` - Chooses mock or HTTP control plane. - `electron/yinian/mock-control-plane.ts` - Local demo implementation with persisted session/config/registry. - `electron/yinian/http-control-plane.ts` - HTTP implementation scaffold for server integration. - `electron/yinian/storage.ts` - YINIAN-specific storage namespace. - `electron/main/index.ts` - Defers gateway auto-start. - Adds E2E renderer query parameters. - `electron/preload/index.ts` - Exposes `window.yinian`. ### Renderer - `src/stores/yinian.ts` - Auth/session/config store. - Restores session on boot. - Refreshes config and skill registry after login and hotel switch. - `src/stores/yinian-skills.ts` - Local registry and skill sync store. - `src/pages/YinianLogin/` - Login UI. - `src/pages/Today/` - M1 hotel home surface. - `src/pages/YinianSkills/` - Skill registry and sync surface. - `src/components/layout/YinianTenantBar.tsx` - Current hotel switcher and logout. - `src/App.tsx` - YINIAN auth gate, production `/today`, E2E compatibility paths. ### Workspace Packages - `packages/kernel-core` - `packages/kernel-context` - `packages/kernel-adapter-openclaw` - `packages/skill-spec` - `packages/skills-hotel-core` - `packages/ui-kit` These are M1 boundary scaffolds. They are intentionally thin and should harden during M2/M3. ### Tests - `tests/unit/yinian-control-plane.test.ts` - `tests/unit/yinian-store.test.ts` - `tests/unit/yinian-skills-store.test.ts` Inherited ClawX unit and E2E tests are still expected to pass. ## 7. Verification Baseline Last known green run: ```bash pnpm run typecheck pnpm run test pnpm run test:e2e ``` Results: - Typecheck: passed. - Unit tests: 89 files, 572 tests passed. - E2E: 26 passed, 1 skipped. Known non-blocking warnings: - Vitest `MaxListenersExceededWarning`. - Vite dynamic/static import chunk warnings. - Vite large chunk warning. - Playwright/Electron `NO_COLOR` ignored because `FORCE_COLOR` is set. ## 8. M2 Entry Points Recommended next steps: 1. Define real server contract v0. 2. Upgrade Today page into a pilot operations cockpit. 3. Expand Skills Manager status model and UI. 4. Start design system consolidation across Login, Today, Skills, and tenant switcher. See `task_plan.md` for the active phased plan. The first draft of the server contract now lives in `docs/SERVER_CONTRACT_V0.md`.