Last updated: 2026-07-31 KST
Started on 2026-07-31 from docs/windows-ui-ux-handoff.md after fast-forwarding
to b7288a4. This pass is presentation-only: Windows networking, WireGuard,
DNS, route, IPC, elevation, recovery, and portable packaging behavior were not
changed.
Implemented:
- moved shared WinUI colors and styles from
MainWindow.xamltoApp.xaml; - removed the window-level forced Light theme and changed page, card, text, and stroke surfaces to follow WinUI theme resources;
- removed the large circular/donut connection control and replaced it with a
wide labeled primary button plus the
이 PC → 선택 사이트 → VPNflow label; - changed the Home profile/recent-status cards to equal columns;
- split VPN Profiles into separate
프로필 가져오기and저장된 프로필cards; - replaced 900-pixel page widths with stretch layouts capped at 1120 pixels;
- added a narrow-window layout mode that stacks the Home summary cards, Home connection actions, and Profile cards without changing their IPC state;
- added an accessible name to the profile delete action and retained visible text/icon state for primary actions.
Verification on the Windows development machine:
dotnet build windows\\VpnRouter.slnx -nr:false: passed, 0 warnings, 0 errors;dotnet build windows\\VpnRouterVs.sln -nr:false: passed, 0 warnings, 0 errors;- focused test executable: all 30 checks passed;
git diff --check: passed.
Remaining owner-operated UI checks: run the WinUI app on Windows 11 at 1120x780 and a narrow window, then inspect Light, Dark, High Contrast, 100/150/200% scaling, keyboard/Narrator traversal, long Korean text, empty lists, and connecting/failed/connected states. Do not claim those visual checks from XAML compilation alone.
Start with docs/windows-next-session.md. The network proof, dynamic DNS route
lifecycle, AAAA filtering, DNS ownership fail-safe, crash recovery, dashboard,
and portable extraction foundation already exist. Do not restart from the
original greenfield checklist.
The immediate order is:
- Reconcile the current 20-test Windows baseline and the small shared-semantic
gaps (
wwwmedia entry points, rotating-answer proof, 512-route cap). - Finish portable lifecycle and IPC security: version handshake, exact-user pipe ACL, single-instance/reconnect behavior, close semantics, cache retention, and disconnected-only cleanup.
- Run the owner-operated Phase 1/2 launcher matrix.
- Continue the remaining Phase 3 and Phase 4 release gates.
Captive-portal handling is outside v0.1.0. Never change another DNS/security/VPN
product automatically. The signed macOS build-20 results provide product
semantics and tests only; Windows must keep its native service, DNS, adapter,
route, UI, and portable-launcher implementation.
- WireGuard for Windows is an external prerequisite.
- VPN Router does not bundle, redistribute, or silently install WireGuard.
- Users import a WireGuard
.conffrom their VPN provider. - MVP test provider used so far: KeepSolid VPN Unlimited WireGuard config.
- Windows development machine.
- WireGuard installed at
C:\Program Files\WireGuard\wireguard.exe. - KeepSolid WireGuard profile imported as
63543_jp_wg. - Test rules used:
youtube.comnetflix.com
Command:
.\scripts\windows\run-service-dev.ps1Verified:
- WireGuard
.confimport. - PrivateKey stored separately from SQLite via DPAPI-backed file secret store.
- Profile list loads in UI.
- Endpoint summary is visible in profile details.
- Connection preflight works.
youtube.comandnetflix.compre-resolve to IPv4 addresses.
Command:
.\scripts\windows\run-service-dev.ps1 -EnableWireGuardActivationVerified:
- KeepSolid tunnel service creation succeeds.
- VPN interface detection succeeds.
- Example successful log:
Detected VPN interface VpnRtr-0bce1a8871744621878b4426 with index 54.
Issues fixed during this phase:
Tunnel name is not valid- Fixed by shortening tunnel names to
VpnRtr-{24 chars}.
- Fixed by shortening tunnel names to
No such host is knownfrom stale/example endpoint- Root cause was selecting an old test profile with
vpn.example.com. - UI now surfaces Endpoint details and warns on
example.com.
- Root cause was selecting an old test profile with
- Endpoint pre-resolution failure
- Runtime config generation now keeps original Endpoint when DNS pre-resolution fails instead of failing the connection.
- App IPC timeout during connect
- Connect/disconnect IPC timeout increased from 3s to 30s.
Command:
.\scripts\windows\run-service-dev.ps1 -EnableWireGuardActivation -EnableWindowsRouteMutationVerified:
- WireGuard tunnel creation succeeds.
- VPN interface detection succeeds.
youtube.comandnetflix.compre-resolve to 7 total IPv4 addresses./32IPv4 host routes are actually added.- Routes are removed on disconnect.
- Network snapshot restore flow runs.
- Example successful logs:
Pre-resolved youtube.com to 4 IPv4 address(es).
Pre-resolved netflix.com to 3 IPv4 address(es).
Detected VPN interface VpnRtr-0bce1a8871744621878b4426 with index 54.
Added 7 IPv4 host route(s) for profile 0bce1a88-7174-4621-878b-4426f892d285.
Removed 7 recorded route plan(s) for profile 0bce1a88-7174-4621-878b-4426f892d285.
Network restore loaded snapshot from ...
ConnectionOrchestratornow attempts automatic cleanup if connect fails:- stop DNS proxy;
- remove managed routes;
- disconnect WireGuard;
- restore network snapshot.
WindowsDnsSettingsManagernow previews/logs target non-WireGuard adapters before DNS mutation.- DNS mutation fails fast if no active non-WireGuard adapter is found.
WindowsNetworkSnapshotStorelogs each IPv4 DNS restore operation.- Manual recovery script added:
.\scripts\windows\restore-network-dev.ps1If DNS mutation was enabled and DNS is broken:
.\scripts\windows\restore-network-dev.ps1 -ResetDnsToDhcpAfter the safety changes, run:
dotnet build windows\VpnRouter.slnx --no-restore -nr:false
dotnet run --project windows\VpnRouter.Tests\VpnRouter.Tests.csproj --no-buildThe focused executable contains 26 checks as of 2026-07-28. Expected tests include:
PASS Parse valid WireGuard config
PASS Prepare import sanitizes private key
PASS Reject missing peer section
PASS Reject invalid CIDR
PASS Parse DNS AAAA query
PASS Create empty DNS NoError response
PASS Parse DNS IPv4 answers
PASS Proxy returns empty response for target AAAA query
PASS Record concurrent DNS observations
PASS Batch concurrent dynamic route discoveries
PASS Refresh repeated managed route expiration
PASS Retain rotating managed route answers
PASS Reject route plan above limit before mutation
PASS Validate backend protocol and payload identity
PASS Restrict service pipe to launching user
PASS Retain active and previous portable cache
PASS Create bounded troubleshooting summary
PASS Expire only eligible managed routes
PASS Force WireGuard runtime routing table off
PASS Split WireGuard default allowed IPs
PASS Keep WireGuard endpoint when DNS pre-resolution fails
After the connected-reboot recovery run on 2026-07-28, both
windows\VpnRouter.slnx and windows\VpnRouterVs.sln built again with zero
warnings and zero errors, and all 26 focused checks passed.
Completed on 2026-07-28 without enabling DNS, WireGuard, or route mutation.
- Both
windows\VpnRouter.slnxandwindows\VpnRouterVs.slnbuild with zero warnings and zero errors on Windows x64 with .NET SDK 10.0.302. - The focused executable passes all 22 checks.
- Media expansion now includes explicit
www.youtube.comandwww.netflix.comentry points while retaining the existing CDN families. - A focused rotating-answer check proves that an address omitted by a later DNS response remains managed until its original expiration; the new address gets its own 15-minute lifetime.
- A profile's combined static, dynamic, and VPN DNS plan is limited to 512 IPv4 host routes. An over-limit plan fails before the route manager invokes Windows mutation or writes the updated managed-route snapshot.
- The existing restore script was inspected without running it and without
using
-ResetDnsToDhcp.
Completed on 2026-07-18 with AdGuard temporarily stopped.
Verified:
- WireGuard runtime config uses
Table = off. - Default
AllowedIPsare split into equivalent/1ranges so WireGuard does not enable its full-tunnel firewall. - The normal Wi-Fi default route remains active.
- Seven site IPv4 routes plus one VPN DNS route are added through the WireGuard interface.
- The DNS proxy uses the WireGuard profile DNS server.
- An A query for
youtube.comreturns four IPv4 answers. - An AAAA query for
youtube.comreturns an empty successful response. - Recovery removes the VPN interface and routes and restores the original DNS server.
Environment conflict:
Adguard Serviceintercepts local UDP port 53 responses on this machine.- Preflight reports the conflict and refuses connection while AdGuard is running.
- AdGuard must be paused before DNS mutation until coexistence is designed.
Safety fixes:
- DNS proxy port binding is verified before Windows DNS is changed.
- Windows UDP connection-reset behavior no longer terminates the proxy loop.
- Upstream DNS requests have a timeout and use the VPN profile DNS server.
- DNS and site routes are installed before Windows DNS mutation.
- Disconnect cleanup continues through all steps after an individual failure.
- The recovery script restores DNS from the saved snapshot by default.
- The unsupported
Set-DnsClientServerAddress -AddressFamilyargument was removed.
Completed on 2026-07-18 with scripts/windows/test-browser-routing-dev.ps1 running as administrator.
Verified:
- Chrome opened YouTube, Netflix, and Example Domain using an isolated test profile.
- The DNS proxy observed seven matching A queries, including YouTube and Netflix subdomains.
- Dynamic A answers were added to the WireGuard interface in short batches.
- The WireGuard interface
/32route count increased from 10 to 30 while the pages loaded. - Concurrent observation writes no longer fail with file-sharing errors.
- The test runner stops Chrome before reading the observation snapshot, so result collection terminates reliably.
- Cleanup restored Wi-Fi DNS to
192.168.1.1, removed the WireGuard adapter, restarted AdGuard with automatic startup, and removed the temporary Chrome DNS-over-HTTPS policy.
Result artifact:
%LOCALAPPDATA%\VpnRouter\logs\browser-routing-result.json
Completed on 2026-07-18.
- Repeated DNS answers refresh the existing route expiration instead of creating duplicate entries.
- Dynamic site routes expire after 15 minutes without another matching answer.
- A maintenance task runs every minute while the DNS proxy is active and removes expired routes.
- The VPN DNS route uses a persistent lifetime and is only removed during disconnect cleanup.
- Expired-route cleanup and disconnect cleanup remove routes in a single PowerShell batch.
- Concurrent observation writes and dynamic route accumulation have focused tests.
- The test suite now contains 16 passing checks.
- The administrator Chrome test observed 7 matching DNS requests and 20 new
/32routes; repeated answers refreshed 4 existing routes. - Final cleanup left
managed-routes.jsonempty, restored DNS to192.168.1.1, removed the VPN adapter, and restarted AdGuard.
Completed on 2026-07-18.
- A single privileged PowerShell worker is reused for route add/remove batches instead of spawning a process for every batch.
- Commands use a request-ID protocol over redirected standard input/output and propagate terminating errors to the service.
- Cancellation or protocol failure discards the worker so a later command cannot consume stale output.
- Service disposal closes the worker input pipe and terminates it if it does not exit promptly.
- A focused test verifies that multiple commands reuse the same worker PID and that command failures propagate.
- The administrator Chrome test completed with one worker start, zero route-batch timeouts, zero withheld DNS responses, and zero DNS proxy failures.
- Chrome loaded YouTube, Netflix, and Example Domain while 20 new VPN
/32routes were installed.
Completed on 2026-07-18.
- The first screen now focuses on connection state, VPN profile, routed sites, and the primary connect action.
- Profile management, protection mode, diagnostics, and network recovery are available in collapsed secondary sections.
- Site removal uses a standard delete icon with a tooltip, and import/add/recovery actions use familiar system icons.
- Technical endpoint details are no longer shown in the main profile summary.
- The layout uses restrained 6 px framing, stable 960 px content width, and theme resources for light/dark mode.
- The x64 app build completed with zero warnings and the 1120 x 780 rendered window was checked for clipping and overlap.
Completed on 2026-07-18.
- A connection marker is written before VPN/DNS/route mutation and cleared only after complete cleanup.
- The named-pipe server waits for startup recovery before accepting commands.
- A failed startup recovery leaves diagnostics available but blocks new connect commands.
- Startup recovery removes all recorded routes and stale
VpnRtr-*tunnels, restores DNS, and clears recovery state. - A forced process termination test left DNS at
127.0.0.1, one VPN adapter, 26 managed routes, and AdGuard stopped. - Restarting only the service restored DNS to
192.168.1.1, removed the adapter and routes, restarted AdGuard, and cleared both recovery markers.
Result artifact:
%LOCALAPPDATA%\VpnRouter\logs\startup-recovery-result.json
Revised on 2026-07-19 after dogfooding feedback.
- VPN Router no longer stops, disables, or otherwise changes AdGuard or another third-party service.
- Preflight checks actual exclusive availability of local UDP port 53 instead of looking for a product or service name.
- The DNS proxy binds the port exclusively and proves response ownership with a random local self-test query before Windows DNS is changed.
- Response ownership is checked every five seconds while connected.
- If another DNS/security product takes or intercepts the response path, VPN Router fails safe by disconnecting and restoring DNS, routes, and the WireGuard tunnel.
- The old AdGuard handoff file is read only to restore state left by an earlier build; new connections never create it.
- Chrome and Edge secure-DNS policies are inspected during connection-plan validation.
- Installed browsers without an explicit
DnsOverHttpsMode=offpolicy receive a user-facing warning. - Secure-DNS policy interpretation has focused tests.
Completed on 2026-07-18 with one remaining player-level limitation.
youtube.comexpands internally to Googlevideo, YTImg, YouTube API, GGpht, and YouTube NoCookie domains.netflix.comexpands internally to Netflix video, image, service, and external asset domains.- Two user rules expanded to 12 effective routing rules without changing the saved UI list.
- The browser test observed Googlevideo, YTImg, GGpht, NflxSo, and NflxExt DNS traffic and installed 37-44 new VPN routes depending on CDN rotation.
- Netflix Fast identified the VPN exit as Tokyo, Japan.
- A Googlevideo media probe returned HTTP 200 and VPN traffic increased by about 11.3 MB.
- YouTube returned playability
OK, but automated Chrome still displayed a player error and did not advancecurrentTime. - Netflix opened its public title page and CDN requests used the VPN; catalog/playback verification remains account-dependent.
- Graceful disconnect restored DNS, removed the VPN adapter, restarted AdGuard, and cleared recovery state.
Implemented and automatically verified on 2026-07-28 without starting the elevated backend or mutating DNS, routes, or WireGuard.
- Launcher and desktop readiness now require a matching protocol version, product version, and payload identity. A stale or differently built backend is rejected before the UI is enabled.
- The portable launcher passes the original Windows user SID to the elevated
backend. The named pipe ACL contains only that SID, Administrators, and
LocalSystem; the broad
InteractiveSidrule was removed. - The owner defined the portable release as current-user-only and waived a live
second-account run on the single-user release machine. The exact-user ACL
remains covered by the focused test. Any future installer must explicitly
distinguish
Current userfromAll usersand configure storage, service registration, and ACLs to match that choice. - The desktop app is single-instance per interactive user session. A second process signals the first window instead of creating a duplicate dashboard.
- Closing the UI keeps a connected backend alive. When the backend reports
Disconnected, the UI requests graceful backend shutdown. - Reopening derives state from the existing backend rather than an optimistic UI flag.
- Portable cache cleanup is refused unless disconnected, retains the active and
immediately previous valid payload, and only targets
%LOCALAPPDATA%\VpnRouter\app. Profiles and DPAPI secrets are outside that scope. - Troubleshooting output no longer previews network snapshots, route files, or DNS observations. It contains schema-versioned bounded counts and flags only.
- App, backend, launcher, and manifest versions are aligned to
0.1.0; trimming and ReadyToRun are disabled for the portable Release path. - The unused
systemAIModelsrestricted capability was removed. scripts\windows\verify-release.ps1verifies version, checksum, extraction, and payload completeness. It can require a valid Authenticode signature.- Two consecutive Release builds produced the same 195,529,964-byte artifact and
SHA-256:
54D37DE05EDA397EB5BB4059EF76D98CC8DE920006796E5DE49966BAD7D236BC. - The owner chose an unsigned
0.1.0public preview because a commercial code-signing certificate is not cost-effective. The remaining local lifecycle matrix, artifact security scan, and exact release tag remain pending; the owner later waived clean-machine and fresh SmartScreen-reputation testing.
The initial launcher and disconnected checks were completed without pressing
Connect on 2026-07-28. A second run exercised a real connection.
- The artifact checksum matched the recorded unsigned candidate before launch.
- The first portable launch produced one elevated backend and one dashboard with no active-connection marker.
- A second launch exited with code 0 while both backend and UI process counts remained one and both PIDs remained unchanged.
- Closing the disconnected UI caused both UI and backend to exit gracefully.
- Disconnected cache cleanup retained the active and previous valid caches. A later corrected-candidate run added one synthetic older valid cache under the portable cache root; cleanup removed only that cache, retained both pre-existing valid caches, and left user-data metadata and network state unchanged.
- A newly generated schema-v1 troubleshooting report contained 19 lines and no private-key label, known media domain, or IPv4-address pattern.
- The first UAC cancellation attempt was approved and completed as a normal
launch. A later normal-Explorer launch was cancelled by selecting
No; no VPN Router process, tunnel, loopback DNS owner, active marker, or managed route remained, while Wi-Fi, automatic DNS, DNS/HTTPS, the default route, and AdGuard stayed healthy. - The final state was zero VPN Router processes, no active-connection marker, and two valid portable cache directories.
- While connected, closing the UI preserved the backend PID, tunnel adapter, loopback DNS ownership, and active marker.
- Reopening the portable executable reused the existing backend and reported
Connected. - Force-terminating only
VpnRouter.Appalso preserved the originalVpnRouter.ServicePID, tunnel adapter, loopback DNS ownership, and active marker. Relaunching created one UI, reused that backend, and resynchronized toConnected. - Connected portable-cache cleanup was refused with no deletion.
- A normal privileged disconnect removed the tunnel adapter, loopback DNS
ownership, active marker, and all managed-route records. The baseline default
route remained, AdGuard stayed
Running/Automatic, and the UI and backend exited. - Force-terminating the elevated
VpnRouter.Servicewhile connected left the UI, active marker, 34 managed-route records, tunnel adapter, and loopback DNS ownership as the expected crash state. Relaunching started a new backend, removed all of that owned state during startup recovery, and reportedDisconnectedwith no active profile. The default route and AdGuard state were unchanged. - Stale-backend rejection passed with the corrected unsigned candidate. The
owner accepted the 10-run automated DNS ownership cleanup evidence as
sufficient for
v0.1.0and waived a live external collision. The owner also waived the clean-machine/missing-WireGuard/SmartScreen-reputation run and a live different-account run for the current-user-only portable release. Exact-user ACL enforcement remains automatically verified.
Continue the pending owner-operated unsigned lifecycle checks in
docs/windows-release-hardening.md, then repeat the matrix with the exact unsigned
public-preview candidate on a clean Windows 11 x64 machine. External player
automation and account-dependent Netflix checks are not release blockers.
The connected-reboot recovery check passed on 2026-07-28 with the exact recorded
unsigned candidate. The post-reboot baseline had zero VPN Router processes and
retained the expected active marker, 38 managed-route records, one tunnel adapter,
and one loopback-DNS owner. The next launch removed all four classes of owned
state before IPC reported Disconnected with no active profile. One normal
default route remained, AdGuard stayed Running/Automatic, and DNS and HTTPS
connectivity succeeded over the current mobile hotspot. No saved Wi-Fi profile
or third-party product was changed.
Fixed and retested on 2026-07-28 after a real Wi-Fi outage was recovered by changing Windows IPv4 DNS back to automatic.
- The network snapshot previously recorded only the effective DNS server list.
Restoring a DHCP-provided server list with
-ServerAddressessilently changed the adapter from automatic DNS to a manual server address. - IPv4 snapshots now also record whether the adapter DNS source is automatic.
Automatic snapshots restore with
-ResetServerAddresses; manual snapshots continue to restore their saved server list. - The development recovery script follows the same automatic/manual rule.
- Three non-mutating regression checks cover automatic, manual, and legacy snapshots. The focused executable passed all 29 checks.
- Both Windows solutions built sequentially with zero warnings and zero errors.
- A corrected unsigned portable dogfood artifact passed extraction and checksum
verification. Its SHA-256 is
A4D41597A1C25373AC70FF1029299533DE9065178B3DC823E5CB325E652FA2F1. - A real connect/disconnect run captured
Wi-Fi 2IPv4 DNS as automatic before mutation. While connected, loopback DNS ownership, DNS resolution, and HTTPS connectivity succeeded. After disconnect, the adapter remained in automatic DNS mode, loopback DNS was absent, resolution and HTTPS succeeded, managed routes and the VPN tunnel were absent, and AdGuard remainedRunning/Automatic. - A physical reboot after the corrected disconnect passed. Wi-Fi returned
Upwith DHCP and automatic IPv4 DNS enabled, the single alive default route used Wi-Fi, and DNS plus HTTPS connectivity succeeded. No VPN Router process, tunnel adapter, or loopback DNS owner remained, and AdGuard stayed running. - The corrected candidate rejected a temporary protocol-99 backend response, showed its error dialog, and exited 1 without launching the elevated backend or desktop app. Route, DNS, recovery-file, tunnel, and AdGuard state remained unchanged.
- A live DNS-ownership-loss attempt added two temporary firewall rules scoped only to the VPN Router backend and loopback UDP port 53. Windows loopback handling bypassed the rules, so that attempt did not satisfy the release row by itself. Both rules were removed. Normal IPC disconnect then cleared 38 managed routes, the tunnel, loopback DNS, and the active marker; DNS/HTTPS and AdGuard remained healthy.
- A test-only DNS controller now injects an ownership failure into the production
connection health monitor and disconnect orchestration without exposing a
command through product IPC or UI. Recovery and legacy-filter paths use a
temporary directory, so the test does not touch LocalAppData or AdGuard. The
test proves DNS stop, managed-route removal, VPN disconnect, network-snapshot
restore, active-marker cleanup, and failed-state reporting. All 30 focused
checks passed 10 consecutive runs, and both Windows solutions built with zero
warnings and zero errors. The owner accepted this evidence as satisfying the
v0.1.0DNS ownership-loss gate; it is not represented as a live external collision. - A current-source pre-commit portable build passed version, checksum, and
extraction verification. It was intentionally unsigned, measured 199,261,420
bytes, and had SHA-256
B4E2A75D1F3DACCE025D734BE3C880AA1609ECE7AF5C8E490135451C5BE5879C. A Windows Security custom scan with enabled real-time protection and current-day signatures reported zero candidate-specific detections. The extractedapp/backendpayload had no configuration, key/certificate, profile, recovery, diagnostic, reparse-point, or out-of-root files. This is not the final tag artifact and requires a post-commit rebuild and rescan. - A sanitized-profile candidate run passed import, rename, rule add/list/remove, connection-plan validation, and delete. Existing profile count, secret-file names, and network state were unchanged afterward, and the disconnected app/backend exited normally. No real configuration or private key was read.
- Avoid reading raw
.confcontents unless the user explicitly approves; it contains PrivateKey. - It is safe to inspect Endpoint lines only if needed, but prefer UI/summary output.
- Avoid enabling DNS mutation until the recovery script and current build are confirmed.
- Keep
.slnxandVpnRouterVs.slnboth building; Visual Studio uses the classic.slnmore reliably.
The cross-platform requirement audit found that the Windows Settings Protection Mode toggle claimed selected sites would be blocked if VPN routes could not be applied, but the value was only logged and added to connection-plan checks. It did not change DNS, route, VPN, recovery, or fail-safe behavior.
The false user-visible promise and its unused IPC/orchestrator parameter were
removed. Settings now describes the service's actual mandatory behavior: on DNS,
VPN, or managed-route safety loss, clean up only VPN Router-owned DNS, routes,
WireGuard connection, recovery marker, and network snapshot without changing
another VPN or security product. This matches
docs/platform-parity-contract.md.
This edit was made on the Mac parity pass, where dotnet is unavailable.
Therefore the Windows solutions and focused test executable must be rebuilt and
rerun on Windows before a release candidate is regenerated. No Windows runtime or
artifact claim is made from this source-only correction.
Follow-up cross-target evidence used an official .NET 10.0.301 arm64 SDK unpacked
only under /private/tmp:
- Core, IPC, Networking, VPN, Launcher, Service, and Tests compiled with zero
warnings and zero errors using
EnableWindowsTargeting=true; - 28 of the 30 focused checks passed under the macOS .NET runtime;
- the persistent PowerShell worker check could not start
powershell.exe, and the service-pipe ACL check reported that Windows Principal is unsupported; - the WinUI project restored, but its Windows-only
XamlCompiler.execould not execute on macOS;xmllintseparately confirmed thatMainWindow.xamlremains well-formed XML.
These results validate the changed IPC/service/test call sites but do not replace the required Windows build of both solutions, all 30 native test results, WinUI XAML compilation, or signed recovery/UI smoke checks.