fix: close and recreate macOS windows safely

This commit is contained in:
鲨鱼辣椒
2026-09-29 19:50:25 +08:00
parent f443f3bc66
commit b5e6c663ef
19 changed files with 1079 additions and 172 deletions

View File

@@ -0,0 +1,60 @@
# Task: Fix native window close and macOS fullscreen lifecycle
## Identity
- Task ID: 20260929-window-close-58c6a9de
- Mode: Feature
- Branch: codex/20260929-window-close-58c6a9de-window-close
- Worktree: /Users/chillishark/Makelore 麦洛/.codex-worktrees/makelore/20260929-window-close-58c6a9de
- Base commit: f443f3bc668dfc6c9df111506d739d343ee82bba
- Owner: codex
- Status: Ready for Integration
## Scope
- Implement native macOS red close as real window destruction, preserving yellow minimize and green native zoom/fullscreen; fix closing from fullscreen and reopening all window-bound services.
## Intent And Constraints
- User explicitly approved changing code after red-close left a black fullscreen Space; manually exiting fullscreen cleared it. Do not replace the installed or running trial app, merge main, publish, or alter concurrent teacher-composer work. Preserve active Main-owned tasks, authentication, project data and persisted drafts.
## Outcome
- macOS red close now destroys the window. Fullscreen close waits for native leave-full-screen before closing; repeated close requests are coalesced and Cmd+Q retains the existing quit lifecycle. Yellow minimize and green native zoom/fullscreen behavior are preserved. Windows/Linux retain close-to-tray.
- Main-owned Host API, coding runtime, authentication and task leases remain alive without a window. Dock activation, tray and menu recreate the window with current IPC/dialog owners, updater notifications and browser presentation callbacks; renderer leases are isolated by WebContents and released on destruction.
- The shared browser module survives window replacement, while each native view retains its original owner. Reopening waits for old preview cleanup; an already cancelled open cannot create a late view or clear its successor. Missing host-window mount failures clean up their view.
- README describes the native control behavior. Changes are isolated on the task branch; the primary checkout, installed app and running trial app were not modified or updated.
## Verification
- Focused unit verification: 152 passing tests across 12 distinct files covering native close, focus/quit, reopen IPC/menu/tray/dialogs, browser adapter/core/routes, background lifecycle and updater. The final browser core/routes run passed 97 tests. Three delayed-cleanup regressions cover close/reopen, preview replacement and project switching; the latter two failed before the epoch fix (unexpected generation 3 and stale-operation rejection) and passed after it. A fourth regression covers view cleanup on mount failure.
- Two real macOS Electron E2E passed after the final build (11.8 seconds): three window generations/two closes, surviving Main PID, working minimize/zoom and IPC, new native preview attachment/events, old preview destruction, native leave-full-screen before closed, reopened normal window and clean app.quit exit. Fixtures use isolated temporary HOME/userData and loopback preview, never the running user apps.
- corepack pnpm run typecheck passed. Scoped ESLint across every changed TypeScript file, build:vite and git diff --check passed.
- Expanded Main typecheck remains blocked by 66 pre-existing diagnostics. An independent exact-base archive comparison against f443f3bc668dfc6c9df111506d739d343ee82bba found 66 identical diagnostics, zero added/removed (normalizing source line/column and checkout paths); final rerun matched. Logs: /tmp/makelore-window-close-main-types-final.txt and /tmp/makelore-window-close-build-final.log.
- Independent review found and verified the now-fixed close/open race; final review found no remaining blocking findings. Project-doc structure and task-aware drift checks passed.
## Follow-ups
- Integrate the committed task branch when requested, then rebuild/update the intended app. This task intentionally delivers code only; live app replacement and main-branch integration were not authorized by the latest request.
- Expanded Main TypeScript baseline errors remain outside this task.
## Promotion Candidates
- Targets: .project-docs/30-worklog/current-state.md and .project-docs/20-architecture/system-overview.md. Proposal: record macOS red-close/window-recreation semantics and the process-owned services / window-owned presentation boundary. Evidence: user explicitly approved red close with yellow/green preserved, focused unit coverage and native macOS E2E. Future impact: new services must resolve the current window dynamically and retain active Main leases when windows close; they must not dispose process-scoped runtimes on window destruction. Semantic conflicts: replaces the prior macOS hide-on-close implementation; no accepted ADR requires that behavior. Human confirmation: already supplied for this product change; canonical promotion remains for an integration task.
## Project Context Loaded
- Task: 20260929-window-close-58c6a9de; feature mode; owned branch codex/20260929-window-close-58c6a9de-window-close; owned worktree as Identity; base f443f3bc668dfc6c9df111506d739d343ee82bba. Ownership start/status passed.
- Read: AGENTS.md; entry read-before-planning, memory-index and planning-gate; active record; positioning; integrated current-state; decision index and lifecycle/ADR-006 references; system-overview/module-map/data-flow; business-rules; success-criteria; evidence/reflection/commitments indexes. Large historical documents were read with task-relevant lifecycle sections independently reviewed by a subagent.
- Project: Main owns system integration and background work; Renderer consumes snapshots. Existing product has Code, Canvas, Robot and published teacher identities. Template placeholders remain in early positioning and are not task authority. Latest user-approved shortcuts/publishing stay untouched.
- Other local tasks: task-context registry reviewed, with every peer task record read for scope/constraints/promotions. Active teacher-composer work is isolated and concerns teacher input/model contracts; old help-label patch and trial/publication tasks must not be overwritten. Other ready tasks are read-only. No native-close semantic conflict.
- Relevant constraints: active/uncertain runs retain Main leases while window is absent; close removes native preview view/debugger and renderer leases only; reopening hydrates snapshots and never replays mutations. Cmd+Q retains bounded shutdown. No accepted ADR requires close-to-hide on macOS.
- Evidence: installed Main intercepts close with preventDefault + hide without fullscreen lifecycle; exiting fullscreen restored user desktop. Green controls remain native.
- Modules: Main index/close lifecycle, window-bound IPC/dialogs/tray/menu/updater, native browser adapter, focused unit and Electron tests.
- Gate: Passed.
## Plan
1. Separate process services from recreatable window bindings; implement safe fullscreen close.
2. Cover repeat close, reopen, leases, dialogs and preview attachment; run focused unit tests, typecheck/lint/build and isolated Electron tests.
3. Review diff, record verified results and prepare a commit/patch for integration.