src/main/index.ts → main.ts and src/preload/index.ts → preload.ts, so the process entries stop occupying the barrel-reserved index filename (§6.4) without needing an exemption list. The rename is wired through electron.vite (main build.lib.entry — rollupOptions.input would bypass electron-vite's output-format detection — and the preload input key), package.json main (out/main/main.js), WindowManager's default preload filename, MainWindowService's webview preload path, and DbService's slow-query stack filter, which matches the bundled artifact name. preload.d.ts becomes globals.d.ts: sharing preload.ts's basename makes TypeScript drop the .d.ts as that file's presumed output declaration, and tsgo only applies its global Window augmentation when the declaration sorts before its importer, so the file keeps a distinct, alphabetically-early name. Entry-path mentions in code comments and reference docs follow.
Make the IpcApi docs explicit about three things surfaced in review:
- overview: Why Narrow the Surface (before/after + the type/cheat-sheet/audit wins), Direction Cheat Sheet (IpcRoute vs IpcEventName + out-of-scope), and No One-Way R->M Primitive (every R->M is invoke/handle; void still round-trips).
- migration guide: Escape Hatch criteria (direction gate then frequency) with Tab_MoveWindow as the sole qualifying carve-out, its two hard conditions (still gated, still documented), and scope discipline for the sibling one-off channels; add Tab_MoveWindow to the Not In Scope table.
- README + usage: navigation pointers and the R->M / M->R high-frequency asymmetry (M->R stays via class B, R->M may escape).
The per-domain schemas/__tests__ (window + selection) asserted zod
primitives: that z.boolean() rejects a string, that z.infer yields boolean,
that never-parsed output schemas round-trip — i.e. they tested zod, not our
code. The route inventory they locked is already enforced at compile time by
IpcHandlersFor exhaustiveness plus the global IpcRoute union test.
Remove all four. Document the boundary across the IPC docs (usage /
schema-guide / migration-guide): test the handler (real behavior), not the
schema; business validation lives in the handler/service, so a schema worth
unit-testing effectively never arises.
Collect the WindowManager caller-window controls (close / minimize / maximize /
unmaximize / set_full_screen / is_maximized / is_full_screen / get_init_data) and
the three directed window events (maximized_changed / fullscreen_changed / reused)
onto the IpcApi framework, replacing the legacy this.ipcHandle registrations, the
hand-written preload windowManager namespace, and the IpcChannel enums.
- Requests: ctx.senderId addresses the caller window (was getWindowIdByWebContents);
fire-and-forget controls return void, queries keep their read type.
- Events: directed IpcApiService.send to the affected window, never broadcast.
- openSettings is a navigation concern misfiled under windowManager — moved to
window.api.settings.openSettings (still legacy IPC, not yet on IpcApi).
- WindowManager_Open was dead (no renderer/preload consumer) — deleted.
- MainWindow_* (main-window singleton ops) intentionally left on legacy IPC.
Behavior verified equivalent before/after by independent review.
First real domain migration onto IpcApi. Collects the selection feature's
6 request channels and 2 main->renderer events off their dedicated
IpcChannel entries and the hand-written preload bridge onto the unified
framework.
- shared/ipc/schemas/selection.ts: request zod schemas + event types;
actionItem bound to SelectionActionItem via z.ZodType for definition-site
schema/type sync
- main/ipc/handlers/selection.ts: thin adapters delegating to
SelectionService; pin_action_window routes straight to
wm.behavior.setAlwaysOnTop(ctx.senderId), dropping the id->window->id
round-trip
- SelectionService: remove registerIpcHandlers and pinActionWindow; emit
the toolbar events via directed IpcApiService.send(toolbarWindowId, ...)
- renderer (toolbar/action/settings): ipcApi.request(...) for calls,
useIpcOn(...) for events
- remove window.api.selection from preload and the Selection_* IpcChannel
enum entries
Behavior-preserving (independently verified): the only delta is
pin_action_window dropping the unreachable untracked-window fallback, now a
benign no-op when ctx.senderId is null. Documents the z.ZodType mirroring
convention in ipc-migration-guide.md.