diff --git a/CHANGELOG.md b/CHANGELOG.md index 4b3538dee..f85d0a517 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,33 @@ # Changelog +## 1.1.3 - 2026-07-26 + +### Changed + +- Refreshed the native title bar, tab strip, pane headers, dividers, window + controls, and terminal-shell palette to match the visual language used on + winterm.dev while preserving existing terminal and pane behavior. +- Regenerated the complete Windows application, package, tile, ICO, and High + Contrast artwork set from the canonical `assets/winterm/icons/winterm.svg` + source. +- Updated application, package, PowerShell module, About, Workspace fallback, + and release metadata to `1.1.3` with intended tag `v1.1.3`. + +### Fixed + +- Wrapped the tab strip and bottom border in a single XAML content container, + resolving the duplicate `ContentPresenter.Content` assignment that blocked + both Debug and Release builds. + +### Distribution + +- Publishes the website-aligned native shell as the verified x64 Setup EXE and + Portable ZIP. +- Workspace schema 2, docking model 1, shell protocol 1, and theme schema 1 + remain unchanged. +- The Setup EXE is not Authenticode-signed; Windows may display Unknown + Publisher or SmartScreen, so verify it with `SHA256SUMS.txt`. + ## 1.1.2 - 2026-07-24 ### Fixed diff --git a/README.md b/README.md index 65ce75f03..59d234fa9 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ application downloads are: - `winTerm--setup-x64.exe` — current-user or all-users installation; - `winTerm--portable-x64.zip` — extract and run without installation. -The current source version is `1.1.2`. See the +The current source version is `1.1.3`. See the [latest official Release](https://github.com/HelloThisWorld/winTerm/releases/latest) for the complete published asset list and checksums. @@ -39,7 +39,7 @@ Release. No MSIX certificate, Developer Mode, Visual Studio, Windows SDK, or `Add-AppxPackage` is required to install a release EXE. See [installation guidance](docs/user/installation.md) and the -[1.1.2 release notes](docs/releases/1.1.2.md). +[1.1.3 release notes](docs/releases/1.1.3.md). ## Core features @@ -84,8 +84,8 @@ Use PowerShell 7 and the Microsoft Terminal toolchain described in .\scripts\winterm\build.ps1 -Configuration Release -Platform x64 -IncludeTests .\scripts\winterm\test.ps1 -Suite Relevant -Configuration Release -Platform x64 .\scripts\winterm\build-unpackaged.ps1 -Configuration Release -Platform x64 -.\scripts\winterm\build-installer.ps1 -Version 1.1.2 -Platform x64 -.\scripts\winterm\build-portable.ps1 -Version 1.1.2 -Platform x64 +.\scripts\winterm\build-installer.ps1 -Version 1.1.3 -Platform x64 +.\scripts\winterm\build-portable.ps1 -Version 1.1.3 -Platform x64 ``` The unpackaged generator uses an unsigned MSIX only as an upstream build diff --git a/docs/current-progress.md b/docs/current-progress.md index 0b25c4421..44af20f6d 100644 --- a/docs/current-progress.md +++ b/docs/current-progress.md @@ -1,39 +1,37 @@ # Current development progress -Last updated: 2026-07-24 +Last updated: 2026-07-26 ## Repository state -- Branch: `codex/fix-v1.1.2-ghost-divider-lines` -- Starting commit: `031f403a1bf7bd36a1df0e9ab1024e2aa78df262` +- Branch: `codex/release-v1.1.3` +- Starting commit: `c5d3ddc61869e041f1b2ef8de743296525c309a0` - Microsoft Terminal upstream revision: `1cea42d433253d95c4487a3037db48197b5e72f4` -- Application and module version: `1.1.2` -- Package version: `1.1.2.0` -- Intended tag: `v1.1.2` +- Application and module version: `1.1.3` +- Package version: `1.1.3.0` +- Intended tag: `v1.1.3` - Supported release target: Windows 11 x64 ## Implemented in the working tree -- Fixed the 1.1.1 ghost pane-divider rendering: the visible divider now uses - the same owner-local, leading-edge alignment model as its pointer target - (vertical dividers align Left, horizontal dividers align Top, offset by the - split position minus half the visible thickness). -- Extended the pane-resize source validation with divider-placement - invariants: shared leading-edge alignment across the visible line and - pointer targets, half-thickness centering on the split position, a guard - against reintroducing the primary-axis Center alignment, a wider pointer - target than the visible line, and divider reattachment across the split, - swap, close, restore, and workspace rebuild paths. +- Refreshed the native title bar, tab strip, pane headers, dividers, window + controls, and terminal-shell palette to match the winterm.dev product + visuals without changing terminal, pane, workspace, or privacy behavior. +- Regenerated Windows package artwork, tiles, ICOs, and High Contrast icons + from the canonical `assets/winterm/icons/winterm.svg` source. +- Fixed the tab-row XAML content structure so the tab strip and bottom border + share one `ContentPresenter` child and compile in both Debug and Release. - Updated application, package, shell module, About, workspace-fallback, and - release metadata to `1.1.2` with intended tag `v1.1.2`. -- Added the 1.1.2 changelog entry and release notes; the README points to the - 1.1.2 release notes while downloads keep the stable `/releases/latest` URL. + release metadata to `1.1.3` with intended tag `v1.1.3`. +- Added the 1.1.3 changelog entry and release notes; the README points to the + 1.1.3 release notes while downloads keep the stable `/releases/latest` URL. ## Evidence -The pane-resize and Smoke source validations pass in Windows PowerShell on -this branch. Compiled native tests, Release application launch, the manual -divider acceptance matrix (split ratios, nesting, DPI scales, High Contrast), -and 1.1.2 installer/Portable creation run through the pull-request GitHub -Actions workflows and remain release gates until their results are recorded. +PR #19 passed Windows PowerShell Smoke validation, GitHub static validation, +x64 Debug and Release builds, relevant upstream tests, Workspace benchmarks, +unpackaged/Setup/Portable creation, current-user and all-users installation +lifecycles, and the exact distribution allowlist. The v1.1.3 release branch +must repeat the applicable validation before its pull request is merged; the +tag-triggered formal Release workflow remains the final publication gate. diff --git a/docs/releases/1.1.3.md b/docs/releases/1.1.3.md new file mode 100644 index 000000000..a9248f710 --- /dev/null +++ b/docs/releases/1.1.3.md @@ -0,0 +1,56 @@ +# winTerm 1.1.3 + +winTerm 1.1.3 brings the native application shell in line with the visual +language used on winterm.dev and makes the canonical winTerm artwork the +single source for every packaged Windows icon. + +## Changed + +- Refreshed the native title bar, window controls, tab strip, pane headers, + dividers, and terminal-shell palette with the winTerm color, density, and + radius tokens. +- Improved active and inactive window presentation, compact tab and pane + treatment, and title-bar product identity without changing terminal input, + rendering, session, or pane-resize behavior. +- Regenerated the application PNGs, package tiles, normal ICO, and High + Contrast ICO variants from `assets/winterm/icons/winterm.svg`. +- Kept the README download entry on GitHub's stable `/releases/latest` route. + +## Fixed + +- The tab strip and its bottom border now share a single XAML content + container. This resolves the duplicate `ContentPresenter.Content` + assignment that initially blocked x64 Debug and Release builds. + +## Validation + +- Windows PowerShell Smoke validation. +- x64 Debug and Release builds with relevant upstream tests. +- Workspace benchmarks and source-boundary validation. +- Unpackaged, Setup EXE, and Portable ZIP creation and verification. +- Current-user and all-users installation, launch, upgrade, isolation, and + uninstall lifecycle tests. +- Exact distribution and public release-asset allowlists. + +## Compatibility + +Workspace schema remains version 2, the docking model remains version 1, the +shell protocol remains version 1, and the theme schema remains version 1. +Existing settings and workspaces load unchanged. Package identity, the +`winterm.exe` alias, privacy boundaries, and Microsoft Terminal coexistence +remain unchanged. + +## Distribution + +Primary x64 assets: + +- `winTerm-1.1.3-setup-x64.exe` +- `winTerm-1.1.3-portable-x64.zip` + +Publisher: `helloThisWorld`. Tag: `v1.1.3`. + +## Signing + +The v1.1.3 Setup EXE is not Authenticode-signed. Windows may display Unknown +Publisher or a SmartScreen warning. Download only from the official GitHub +Release and verify the file against `SHA256SUMS.txt` before running it. diff --git a/scripts/winterm/package-shell-assets.ps1 b/scripts/winterm/package-shell-assets.ps1 index af31eac69..d6d983edc 100644 --- a/scripts/winterm/package-shell-assets.ps1 +++ b/scripts/winterm/package-shell-assets.ps1 @@ -32,9 +32,9 @@ foreach ($relativePath in $sourceAssets) } $version = Get-Content -LiteralPath (Join-Path $repositoryRoot 'shell\shared\version.json') -Raw | ConvertFrom-Json -if ($version.moduleVersion -ne '1.1.2' -or +if ($version.moduleVersion -ne '1.1.3' -or $version.modulePrerelease -ne '' -or - $version.applicationVersion -ne '1.1.2' -or + $version.applicationVersion -ne '1.1.3' -or $version.protocolVersion -ne 1) { throw 'The winTerm Shell asset version metadata is invalid.' diff --git a/scripts/winterm/test.ps1 b/scripts/winterm/test.ps1 index 0fa6a691e..af560b39c 100644 --- a/scripts/winterm/test.ps1 +++ b/scripts/winterm/test.ps1 @@ -101,7 +101,7 @@ function Test-ShellExperienceFoundations } $manifest = Import-PowerShellDataFile -LiteralPath $moduleManifest - if ($manifest.ModuleVersion -ne '1.1.2' -or + if ($manifest.ModuleVersion -ne '1.1.3' -or $manifest.PrivateData.PSData.Prerelease -ne '' -or $manifest.PowerShellVersion -ne '5.1') { diff --git a/scripts/winterm/verify-branding.ps1 b/scripts/winterm/verify-branding.ps1 index 464bc74f2..a6a6145e1 100644 --- a/scripts/winterm/verify-branding.ps1 +++ b/scripts/winterm/verify-branding.ps1 @@ -126,7 +126,7 @@ function Test-Manifest Test-Requirement -Condition ($null -ne $identity -and $identity.Name -eq 'HelloThisWorld.winTerm') -Message "$Path uses package identity HelloThisWorld.winTerm" Test-Requirement -Condition ($null -ne $identity -and $identity.Name -notmatch '^Microsoft\.') -Message "$Path does not use a Microsoft package name" Test-Requirement -Condition ($null -ne $identity -and $identity.Publisher -ceq $ExpectedPublisher) -Message "$Path uses the expected non-Microsoft publisher" - Test-Requirement -Condition ($null -ne $identity -and $identity.Version -eq '1.1.2.0') -Message "$Path uses package version 1.1.2.0" + Test-Requirement -Condition ($null -ne $identity -and $identity.Version -eq '1.1.3.0') -Message "$Path uses package version 1.1.3.0" Test-Requirement -Condition ($null -ne $properties -and $properties.DisplayName -eq 'winTerm') -Message "$Path package display name is winTerm" Test-Requirement -Condition ($null -ne $application -and $application.Id -eq 'winTerm') -Message "$Path application ID is winTerm" Test-Requirement -Condition ($null -ne $visualElements -and $visualElements.DisplayName -eq 'winTerm') -Message "$Path application display name is winTerm" diff --git a/scripts/winterm/verify-version.ps1 b/scripts/winterm/verify-version.ps1 index 41074ed2d..4f0993a7d 100644 --- a/scripts/winterm/verify-version.ps1 +++ b/scripts/winterm/verify-version.ps1 @@ -49,12 +49,12 @@ try $versionPath = Join-Path $repositoryRoot 'src\winterm\Branding\version.json' $version = Get-Content -LiteralPath $versionPath -Raw | ConvertFrom-Json - Assert-Condition ($version.applicationVersion -eq '1.1.2') 'Application version is 1.1.2' - Assert-Condition ($version.packageVersion -eq '1.1.2.0') 'Package version is 1.1.2.0' - Assert-Condition ($version.moduleVersion -eq '1.1.2') 'PowerShell module version is 1.1.2' + Assert-Condition ($version.applicationVersion -eq '1.1.3') 'Application version is 1.1.3' + Assert-Condition ($version.packageVersion -eq '1.1.3.0') 'Package version is 1.1.3.0' + Assert-Condition ($version.moduleVersion -eq '1.1.3') 'PowerShell module version is 1.1.3' Assert-Condition ($version.modulePrerelease -eq '') 'PowerShell module has no prerelease suffix' Assert-Condition ($version.channel -eq 'stable') 'Release channel is stable' - Assert-Condition ($version.tag -eq 'v1.1.2') 'Stable tag is v1.1.2' + Assert-Condition ($version.tag -eq 'v1.1.3') 'Stable tag is v1.1.3' Assert-Condition ($version.workspaceSchemaVersion -eq 2) 'Workspace Schema version remains 2' Assert-Condition ($version.dockingModelVersion -eq 1) 'Docking Model version remains 1' Assert-Condition ($version.shellProtocolVersion -eq 1) 'Shell Protocol version remains 1' @@ -78,7 +78,7 @@ try $moduleManifest = Import-PowerShellDataFile -LiteralPath (Join-Path $repositoryRoot 'shell\powershell\winTerm.Shell\winTerm.Shell.psd1') Assert-Condition ($moduleManifest.ModuleVersion.ToString() -eq $version.moduleVersion) 'PowerShell manifest version matches release metadata' Assert-Condition ($moduleManifest.PrivateData.PSData.Prerelease -eq $version.modulePrerelease) 'PowerShell manifest prerelease matches release metadata' - Assert-Condition ((Get-Text 'shell\powershell\winTerm.Shell\winTerm.Shell.psm1').Contains("`$script:WinTermModuleVersion = '1.1.2'")) 'PowerShell module runtime version matches release metadata' + Assert-Condition ((Get-Text 'shell\powershell\winTerm.Shell\winTerm.Shell.psm1').Contains("`$script:WinTermModuleVersion = '1.1.3'")) 'PowerShell module runtime version matches release metadata' $shellVersion = Get-Text 'shell\shared\version.json' | ConvertFrom-Json Assert-Condition ($shellVersion.applicationVersion -eq $version.applicationVersion) 'Shell asset application version matches release metadata' @@ -86,7 +86,7 @@ try Assert-Condition ($shellVersion.protocolVersion -eq $version.shellProtocolVersion) 'Shell asset protocol version matches release metadata' $releaseHeader = Get-Text 'src\winterm\Branding\ReleaseMetadata.h' - Assert-Condition ($releaseHeader.Contains('ApplicationVersion{ L"1.1.2" }')) 'About metadata application version is 1.1.2' + Assert-Condition ($releaseHeader.Contains('ApplicationVersion{ L"1.1.3" }')) 'About metadata application version is 1.1.3' Assert-Condition ($releaseHeader.Contains('ReleaseChannel{ L"Stable" }')) 'About metadata channel is Stable' Assert-Condition ($releaseHeader.Contains($version.microsoftTerminalUpstreamRevision)) 'About metadata contains the Microsoft Terminal upstream revision' Assert-Condition ($releaseHeader.Contains('WorkspaceSchemaVersion{ 2 }')) 'About metadata contains Workspace Schema version 2' @@ -105,19 +105,19 @@ try Assert-Condition ((Get-Text 'src\winterm\Workspaces\Model\WorkspaceDescriptor.h').Contains('DockingModelVersion{ 1 }')) 'Workspace model remains at Docking version 1' Assert-Condition ((Get-Text 'src\winterm\Shell\Protocol\ShellIntegrationProtocol.h').Contains('ShellProtocolVersion{ 1 }')) 'Shell protocol remains at version 1' Assert-Condition ((Get-Text 'src\winterm\Appearance\Themes\ThemeDescriptor.h').Contains('CurrentThemeSchemaVersion{ 1 }')) 'Theme Schema remains at version 1' - Assert-Condition ((Get-Text 'src\winterm\Workspaces\Persistence\WorkspaceSerializer.cpp').Contains('"1.1.2"')) 'Workspace application-version fallback is 1.1.2' + Assert-Condition ((Get-Text 'src\winterm\Workspaces\Persistence\WorkspaceSerializer.cpp').Contains('"1.1.3"')) 'Workspace application-version fallback is 1.1.3' $releaseWorkflow = Get-Text '.github\workflows\release.yml' Assert-Condition ($releaseWorkflow.Contains("- 'v*'")) 'Release workflow accepts version tags through a generic guarded trigger' Assert-Condition ($releaseWorkflow.Contains("`$expectedTag = `"v`$(`$metadata.applicationVersion)`"")) 'Release workflow derives the expected tag from version.json' Assert-Condition ($releaseWorkflow.Contains("`$metadata.tag -cne `$expectedTag")) 'Release workflow rejects a version metadata tag mismatch' - Assert-Condition ((Get-Text 'CHANGELOG.md').Contains('## 1.1.2 - 2026-07-24')) 'Changelog contains 1.1.2' + Assert-Condition ((Get-Text 'CHANGELOG.md').Contains('## 1.1.3 - 2026-07-26')) 'Changelog contains 1.1.3' if ($RequireTag) { $tag = (& git describe --tags --exact-match 2>$null).Trim() - Assert-Condition ($LASTEXITCODE -eq 0 -and $tag -eq $version.tag) 'Checked-out commit is exactly tagged v1.1.2' + Assert-Condition ($LASTEXITCODE -eq 0 -and $tag -eq $version.tag) 'Checked-out commit is exactly tagged v1.1.3' } Write-Host 'winTerm version consistency verification passed.' -ForegroundColor Green diff --git a/shell/powershell/winTerm.Shell/winTerm.Shell.psd1 b/shell/powershell/winTerm.Shell/winTerm.Shell.psd1 index e7e4a6eb1..7b2d02a22 100644 --- a/shell/powershell/winTerm.Shell/winTerm.Shell.psd1 +++ b/shell/powershell/winTerm.Shell/winTerm.Shell.psd1 @@ -1,6 +1,6 @@ @{ RootModule = 'winTerm.Shell.psm1' - ModuleVersion = '1.1.2' + ModuleVersion = '1.1.3' GUID = 'f65cd8f4-5d25-4a2a-a0d4-58df1ab3dc5a' Author = 'winTerm contributors' CompanyName = 'winTerm' diff --git a/shell/powershell/winTerm.Shell/winTerm.Shell.psm1 b/shell/powershell/winTerm.Shell/winTerm.Shell.psm1 index 9e513f78a..078606b91 100644 --- a/shell/powershell/winTerm.Shell/winTerm.Shell.psm1 +++ b/shell/powershell/winTerm.Shell/winTerm.Shell.psm1 @@ -3,7 +3,7 @@ Set-StrictMode -Version Latest -$script:WinTermModuleVersion = '1.1.2' +$script:WinTermModuleVersion = '1.1.3' $script:WinTermProtocolVersion = 1 $script:WinTermIntegrationEnabled = $false $script:WinTermPromptWrapped = $false diff --git a/shell/shared/version.json b/shell/shared/version.json index 468a87303..5594455fe 100644 --- a/shell/shared/version.json +++ b/shell/shared/version.json @@ -1,6 +1,6 @@ { - "applicationVersion": "1.1.2", - "moduleVersion": "1.1.2", + "applicationVersion": "1.1.3", + "moduleVersion": "1.1.3", "modulePrerelease": "", "protocolVersion": 1 } diff --git a/src/cascadia/CascadiaPackage/Package-winTerm.appxmanifest b/src/cascadia/CascadiaPackage/Package-winTerm.appxmanifest index 8678ea112..1306ecca9 100644 --- a/src/cascadia/CascadiaPackage/Package-winTerm.appxmanifest +++ b/src/cascadia/CascadiaPackage/Package-winTerm.appxmanifest @@ -18,7 +18,7 @@ + Version="1.1.3.0" /> winTerm diff --git a/src/cascadia/WindowsTerminal/WindowsTerminal.rc b/src/cascadia/WindowsTerminal/WindowsTerminal.rc index a0152449b..290d1c5b2 100644 --- a/src/cascadia/WindowsTerminal/WindowsTerminal.rc +++ b/src/cascadia/WindowsTerminal/WindowsTerminal.rc @@ -83,8 +83,8 @@ IDI_APPICON_HC_WHITE ICON "..\\..\\..\\res\\terminal\\imag #if defined(WT_BRANDING_WINTERM) 1 VERSIONINFO - FILEVERSION 1,1,2,0 - PRODUCTVERSION 1,1,2,0 + FILEVERSION 1,1,3,0 + PRODUCTVERSION 1,1,3,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS VS_FF_DEBUG @@ -101,12 +101,12 @@ BEGIN BEGIN VALUE "CompanyName", "helloThisWorld\0" VALUE "FileDescription", "winTerm Terminal Host\0" - VALUE "FileVersion", "1.1.2.0\0" + VALUE "FileVersion", "1.1.3.0\0" VALUE "InternalName", "WindowsTerminal\0" VALUE "LegalCopyright", "Copyright (c) winTerm contributors. Portions copyright Microsoft Corporation.\0" VALUE "OriginalFilename", "WindowsTerminal.exe\0" VALUE "ProductName", "winTerm\0" - VALUE "ProductVersion", "1.1.2\0" + VALUE "ProductVersion", "1.1.3\0" END END BLOCK "VarFileInfo" diff --git a/src/winterm/Branding/ReleaseMetadata.h b/src/winterm/Branding/ReleaseMetadata.h index d85f59d46..a1632c112 100644 --- a/src/winterm/Branding/ReleaseMetadata.h +++ b/src/winterm/Branding/ReleaseMetadata.h @@ -25,7 +25,7 @@ namespace winTerm::Branding { inline constexpr std::wstring_view Publisher{ L"helloThisWorld" }; - inline constexpr std::wstring_view ApplicationVersion{ L"1.1.2" }; + inline constexpr std::wstring_view ApplicationVersion{ L"1.1.3" }; inline constexpr std::wstring_view ReleaseChannel{ L"Stable" }; inline constexpr std::wstring_view CommitSha{ WINTERM_BUILD_COMMIT_SHA }; inline constexpr std::wstring_view BuildTimestamp{ WINTERM_BUILD_TIMESTAMP }; diff --git a/src/winterm/Branding/version.json b/src/winterm/Branding/version.json index 3e70eb035..f049248b5 100644 --- a/src/winterm/Branding/version.json +++ b/src/winterm/Branding/version.json @@ -1,10 +1,10 @@ { - "applicationVersion": "1.1.2", - "packageVersion": "1.1.2.0", - "moduleVersion": "1.1.2", + "applicationVersion": "1.1.3", + "packageVersion": "1.1.3.0", + "moduleVersion": "1.1.3", "modulePrerelease": "", "channel": "stable", - "tag": "v1.1.2", + "tag": "v1.1.3", "workspaceSchemaVersion": 2, "dockingModelVersion": 1, "shellProtocolVersion": 1, diff --git a/src/winterm/Workspaces/Model/WorkspaceDescriptor.h b/src/winterm/Workspaces/Model/WorkspaceDescriptor.h index 3d3d76f30..5adbeffa8 100644 --- a/src/winterm/Workspaces/Model/WorkspaceDescriptor.h +++ b/src/winterm/Workspaces/Model/WorkspaceDescriptor.h @@ -219,7 +219,7 @@ namespace winTerm::Workspaces std::string createdAt; std::string updatedAt; WorkspaceSource source{ WorkspaceSource::User }; - std::string applicationVersion{ "1.1.2" }; + std::string applicationVersion{ "1.1.3" }; uint32_t protocolVersion{ 1 }; uint32_t dockingModelVersion{ DockingModelVersion }; WorkspaceStartupBehavior startupBehavior; diff --git a/src/winterm/Workspaces/Persistence/WorkspaceSerializer.cpp b/src/winterm/Workspaces/Persistence/WorkspaceSerializer.cpp index 4d27df053..8a08b0148 100644 --- a/src/winterm/Workspaces/Persistence/WorkspaceSerializer.cpp +++ b/src/winterm/Workspaces/Persistence/WorkspaceSerializer.cpp @@ -618,7 +618,7 @@ WorkspaceDescriptor WorkspaceSerializer::FromJson(const Json::Value& json, const throw std::runtime_error("The workspace source is not supported."); } workspace.source = *source; - workspace.applicationVersion = StringOrDefault(json, "applicationVersion", "1.1.2"); + workspace.applicationVersion = StringOrDefault(json, "applicationVersion", "1.1.3"); workspace.protocolVersion = UIntOrDefault(json, "protocolVersion", 1); workspace.dockingModelVersion = UIntOrDefault(json, "dockingModelVersion", DockingModelVersion); if (const auto& startup = json["startupBehavior"]; !startup.isNull())