The mocks README described what was mocked but never stated that
tests/__mocks__/main/ is intentionally limited to cross-cutting
infrastructure. Without that boundary in writing, feature-specific
lifecycle services were getting registered into defaultServiceInstances,
bloating the global default surface without serving any other test.
Adds an explicit Scope section with a pattern-selection table, documents
the canonical local-stub pattern for feature-specific lifecycle services
(vi.mock on @application + MockBaseService stand-in), and a Common
Assertions table covering phase, dependencies, IPC handlers, and
disposables. Adds the missing Main PreferenceService section to match the
other three infrastructure service docs. Links the lifecycle README to
the new testing guidance.
- Rename WindowService -> MainWindowService (git mv, preserves blame/log)
- Register WindowType.Main in windowRegistry (singleton, showMode: manual);
MainWindowService drives construction via wm.open and retains business
logic only: IPC handlers, tray-aware close, crash recovery, show/toggle
- 50 call sites renamed (@DependsOn, application.get keys, imports)
WM Dock visibility refactored from visibility-based to existence-based:
- updateDockVisibility predicate drops isVisible/isMinimized check — a
hidden main window must not remove the Dock icon (Cmd+W semantics)
- Add wm.setMacShowInDockByType(type, value) for tray-mode transitions;
keyed by type so services can suppress Dock before the first instance
exists (tray-on-launch path)
- Reduce triggers to window creation, destruction, and type-override
changes; show/hide/minimize/restore no longer affect Dock state
- dockShouldBeVisible initializes true to match Electron's default
MainWindowService uses setMacShowInDockByType for tray-on-launch, close-
to-tray, and reopen-from-tray paths, replacing manual app.dock?.hide()
calls that raced against WM.
Docs updated across window-manager/{README, overview, platform,
api-reference, migration-guide}. New MainWindowService unit test covers
the close matrix (isQuitting, win/linux tray on/off, mac default, mac
tray on_close, fullscreen edge, Dock override assertions) and crash
recovery (first reload vs second-within-60s forceExit).
Phase ordering already guarantees BeforeReady services (PreferenceService,
DbService, CacheService, DataApiService) are ready before WhenReady starts,
so declaring @DependsOn across phases adds noise and misleads readers about
same-phase coupling. The rule existed in lifecycle-overview but was buried
in a bullet; reinforce it in the docs AI assistants scan first.
- CLAUDE.md: add a bullet under the Lifecycle section stating @DependsOn
is for same-phase deps only
- lifecycle/README.md: new "Cross-Phase Dependencies Are Automatic"
callout section and a matching Anti-patterns row
- lifecycle/lifecycle-overview.md: promote the line-87 note to a blockquote
callout and annotate the Dependency Rules table
- lifecycle/lifecycle-decision-guide.md: add Common Mistake #5 with
bad/good code examples