Standalone Merge application presentation
This connected native adaptation follows pinned
src/TortoiseMerge/TortoiseMerge.cpp::InitInstance, its main-frame lifetime and
src/Resources/TortoiseMergeENG.rc File/Edit/View/Navigate/Help commands. It uses
the same IDD_OPENDLG Open/replacement workflow as the existing editor family.
It does not certify that all upstream main-frame commands or dialog layouts are
complete.
TurtleGitLaunchMode.resolve uses the actual Merge command parser before choosing
one of two concrete SwiftUI applications. TurtleGitApplication.main performs
shared rebase-editor and runtime initialization once, then calls either
TurtleGitMacApp.main() or TurtleGitMergeToolApp.main(). Each App declares a
static scene set; there is no unsupported conditional SceneBuilder content. Ordinary document requests and repository /command
requests retain the repository WindowGroup. Recognized tool arguments select a
Settings-only scene, including malformed requests that must report a tool error.
There is no repository window in this scene to create, hide, or flash on screen.
WorkspaceSceneOwner delays the production repository model until the repository
scene actually reads it, avoiding Finder-watch restoration simply from installing
App state objects.
The standalone scene has no RepositoryWindow.onAppear. The application delegate
therefore retains a minimal RepositoryModel(startMonitoring: false, initializePreferences: false) and appearance owner, installs the native settings
service and delivers startup once. It does not install the automatic First Start
Wizard or release-update startup service. Previous-crash prompting is reserved
for ordinary workspace startup. Context Help remains installed for both modes.
The tool refuses automatic untitled-file and Dock-reopen workspace creation;
ordinary workspace behavior remains available. After launch finishes, the
standalone owner requests regular application activation once before its
asynchronous editor presentation. Direct Git execution does not otherwise create
a SwiftUI document window to activate the process. The subsequent native editor
can therefore become the actual key window and acquire its existing guarded menu
contributions; this does not relax commands to use an inactive/background owner.
The existing focused MergeEditorCommandMenu owns Open, Save, Save As and patch
creation, editing, navigation, view options and help. Standard menu roots are
resolved by AppKit Window/Help identities, responder actions, application-owned
keyboard bindings and the known standard App/File/Edit/View scaffold. Native
contributions therefore reuse the macOS-localized roots instead of creating
parallel English File/Edit/View/Help menus. Existing framework identifiers and
captions remain intact; optional TurtleGit identifiers belong to TurtleGit,
without assuming private SwiftUI identifier strings. New Navigate insertion uses
semantic role order. Retirement removes only the contributed commands and
empty roots created by that owner. Its actual model guards,
menu epochs, retired-owner refusal, permission choices and replacement workflow
remain in use. The standalone command provider omits repository New/Open Recent,
Clone/Create/Close Repository, repository actions and unrelated startup commands.
Standard macOS clipboard, Undo/Redo, Window and Quit are retained. A dedicated
Close command (Command-W) supplies the document action missing from a Settings-only
scene. It re-resolves the visible key tool/Open/patch/settings owner, rejects
foreign/closed/retired/sheet/Quit-confirmation owners, and calls performClose.
Existing controller save prompts and load cancellation remain authoritative;
it never force-closes a busy or dirty editor. The
application About entry identifies TurtleGitMerge. Merge Editor Settings continues
to open the shared native settings owner at the Merge page; Appearance remains
available in the global settings navigation, including Light/Dark/System choice.
Save All supplements the focused source menus, using Command-Option-S to avoid the existing native Command-Shift-S Save As binding. The context observes the current model, re-resolves the actual key window on invocation, rejects sheets, field editors, readonly/retired models, pending operations and Quit confirmation, and saves every dirty comparison pane rather than only the active pane. A clean required merged result also participates. Three-file results use the existing owned save flow without marking a repository conflict resolved. Background or closed editors cannot receive a stale Save All invocation.
Tool termination continues to use the existing launch session: approved Quit closes its owned editors, waits for active work and returns the actual saved or discarded result status to the waiting Git process. Selecting a dedicated scene does not replace this protocol with an independent termination path.
Verification scope and remaining acceptance
qa/merge-tool-scene-native-2026-10-18.swift supplies
MergeToolSceneVerification.verify() for the grouped native runner. It checks
ordinary/tool/malformed classification, lazy workspace creation, retained
standalone bootstrap, one-shot activation/delivery, normal startup deferral, suppression
of untitled/reopen workspace requests, independent mandatory-output Save All,
inactive-pane Save All, background/closed/Quit refusal, guarded Close of clean
comparison/Open windows, and actual focused native
menu contributions with retirement, including application-menu replacement after
the editor became key (without a second focus callback), localized root reuse,
role order and preservation of framework roots/anchors after retirement. It uses private preferences/files and owned
invisible windows. The parent batch records actual build/check outcomes after its
checkpoint; this document does not assert a pass before that checkpoint.
The helper fixture does not launch a second SwiftUI App lifecycle. A built-app process/UI smoke is separately needed to demonstrate physical absence of an automatic workspace and actual Settings-only scene menu integration on supported SDK/OS combinations. Displayed light/dark layout, keyboard focus/VoiceOver, minimum-OS/Intel, signed sandbox terminal grants and whole-app source parity remain separate acceptance work. Repository and tool scenes currently share the application bundle identity/name, as the waiting wrapper executes that bundle's binary; no separate installed TurtleGitMerge app bundle is created by this batch.