chore(deps): bump github/codeql-action from 3 to 4#1
Merged
Conversation
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3 to 4. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](github/codeql-action@v3...v4) --- updated-dependencies: - dependency-name: github/codeql-action dependency-version: '4' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com>
FarmLox
added a commit
that referenced
this pull request
May 2, 2026
Addresses every actionable finding from the independent ship-readiness
review at non-repo-files/v1.5.4-ship-readiness-review.md. Findings
that the review flagged but explicitly did not fix here are documented
inline with their reasoning.
Native interop (latent UB; harmless on x64 by ABI luck):
- SHFILEOPSTRUCT: Pack=8 -> Pack=1 to match the Windows SDK's
pshpack1.h declaration. Pack=8 inserted 4 bytes of padding before
pFrom on x64, putting the C# field at offset 16 while the kernel
reads from offset 12 - the shell happened to read field-aligned
bytes that just so happened to look right.
- MSIHANDLE: changed from IntPtr (8 bytes on x64) to uint (4 bytes,
matching `typedef unsigned long MSIHANDLE` in msi.h). The IntPtr
signature would crash on x86 where the calling convention pushes
8 bytes for a 4-byte argument. Cascaded the type change through
Msi.cs and MsiFileInfoService.cs.
- X509Certificate.CreateFromSignedFile result is now disposed too
(was leaked until finalisation; the X509Certificate2 wrapper
duplicates the handle so the inner needs its own using).
Operation correctness:
- F5 keybinding (and any other Re-scan trigger) now gates on
Cleanup.IsOperating and Completion.IsComplete via a new
ScanViewModel.IsExternallyBlocked flag flipped from MainViewModel.
Without this, F5 during a Move started a parallel scan that raced
the active operation.
- EnumeratePatches now throws InvalidOperationException after
MaxConsecutiveNonSuccess just like EnumerateProducts does. The
silent break would have left real-but-superseded patches missing
from the result set, classifying them as orphaned and offering
them for cleanup.
- EnumeratePatches now Array.Clear's its GUID buffers between
iterations, matching EnumerateProducts.
- Pre-flight write probe in CleanupViewModel.MoveAllAsync is now
cancellable: the operationCts is created BEFORE the probe (was
after), so the Cancel button on the operating overlay actually
cancels rather than waiting out the SMB timeout. The probe also
goes through the injected IFileSystem so MockFileSystem-driven
tests don't hit real disk.
- Settings file lost-update race fixed: SaveAfterDelayAsync re-loads
before saving, copies MoveDestination onto the freshly-loaded
AppSettings, then writes. Previously, the cached _settings instance
could clobber updates the detail-window code-behinds wrote
(window-size persistence) while the user was typing in the move-
destination textbox.
- PruneEmptySubdirectories called with CancellationToken.None: best-
effort cleanup, not an operation the user's Cancel should
re-classify a successful Move/Delete as cancelled.
- Move/DeleteFailed status pill now also includes the crash log path,
so users can find detail rather than guess where to look.
- Maximize/Restore button glyph now updates with the window state.
Path leakage under elevation:
- DescribeWriteFailure no longer routes ex.Message into the dialog.
Even an IOException's .Message can carry paths from outside the
user's typed destination (lock-holder process paths, NTFS
resolution chains); under elevation those could be paths from
another user's profile. Caller now writes to crash log first,
passes the log path through DescribeWriteFailure, and the dialog
body shows only the user's own dest plus the log-path pointer.
Resx patterns updated; matching tests inverted.
- ScanViewModel generic-exception catch shows a dialog (was status
pill only, easily missed).
- DispatcherUnhandledException in App.xaml.cs guards against re-
entry: a second exception during the MessageBox's nested message
pump no longer stacks two dialogs / two log entries.
CLI:
- Rejects extra positional args for /s, /d (silent truncation
before); /m allows args[1] only.
- /m PATH path with unquoted spaces ("/m D:\My Backup") used to
become "D:\My" with no warning.
- Three-state exit code: 0 success, 2 partial success, 1 full
failure. Documented in --help. Sysadmin retry policies can now
distinguish "all files failed" from "1 of 100 failed".
- DeletingFiles / MovingFiles status messages take a pluralised
noun parameter so "1 files" is no longer printed for single-
orphan runs.
- Console.CancelKeyPress handler registered BEFORE the mutex
acquisition so a Ctrl+C in the gap prints "Cancelling..."
gracefully.
- Pre-mutex-cancel path also unhooks the cancel handler before
return, matching the post-finally cleanup.
Threading / state:
- ScanViewModel re-samples HasPendingReboot AFTER the scan await,
not before. Sampling before could publish a stale "no pending
reboot" if Windows Update queued a reboot during a multi-second
scan, allowing Move/Delete to enable on stale state.
- PropertyChanged-based MoveDestination binding (was LostFocus): the
400 ms debounce now actually earns its keep (per-keystroke updates
let the placeholder hide on the first character and the Move
button enable as soon as the path becomes non-empty), and the
debounce prevents save thrashing.
- MoveAllAsync uses the captured `dest` consistently (was reading
MoveDestination live for confirmation / move call / restore-hint
string), closing a race where a fast user could change the
textbox between IsInstallerFolderOrChild validation and the Move
service call.
Localisation:
- Strings.en-GB.resx deleted: it was a 1:1 duplicate of the neutral
resx, and the project's NeutralLanguage is en-GB so .NET fallback
already returned the neutral resource for en-GB consumers. The
satellite assembly was loaded but its content was identical.
Maintenance trap eliminated.
- Resx patterns added: Cli.Help.ExitCodes* (the new --help block),
Cli.PendingRebootBlocked, Cli.EventLogPendingRebootBlocked.
UX polish:
- Result overlay tab-cycles inside the overlay's two buttons (was
cycling through main-window buttons behind the overlay until
focus eventually landed on Close).
- Result overlay has a 1px slate border so it reads as a layered
window instead of a free-floating block.
- Click on the dim margin around the result overlay dismisses it.
- Maximize/Restore button glyph swaps between U+25A1 and U+2750.
- Result-screen errors block is now keyboard-focusable so screen
readers can read it (overrides SelectableText style's
IsTabStop=False locally).
- AboutWindow Close button gets AutomationProperties.Name (was
inconsistent with the four other windows' close buttons).
- SubtleLink hyperlinks now underline on hover so the link is
discoverable without relying on colour shift alone.
Tests:
- DescribeWriteFailureTests: inverted to assert the inner exception
message does NOT leak and the log path DOES surface.
- MainViewModelTests timing-coupled debounce wait now reads
CleanupViewModel.MoveDestinationSaveDelay (made internal)
instead of hardcoding 700 ms.
- OrphanedFilesViewModelTests dispose-cancel test uses
TaskCompletionSource (await-based) instead of
DateTime.UtcNow polling.
- PendingRebootServiceTests removed the tautological
Assert.IsType<bool>(svc.HasPendingReboot()) test.
- PruneEmptySubdirectoriesTests gated on the
INSTALLERCLEAN_TEST_PRUNE=1 env var so they don't delete real
installer-folder subdirs on dev/CI hosts.
- InstallerClean.Tests.csproj sets RestorePackagesWithLockFile=true
so test dependency drift can't mask production behaviour.
CLAUDE.md / MEMORY.md drift:
- CLAUDE.md said neutral resx is en-US; actually en-GB. Fixed and
noted the en-GB.resx satellite removal.
- CLAUDE.md said only Core has SupportedOSPlatform; CLI has it too.
Now mentions both.
- "Nothing currently blocking" replaced with a pointer to the latest
ship-readiness review.
- MEMORY.md "no ex.Message to UI" claim qualified with the documented
inline exceptions (DescribeWriteFailure, ScanViewModel's
InvalidOperationException catch).
Findings explicitly NOT actioned (with reasoning):
- #18, #25, #59 are duplicates of #1, #11.
- #31 EventTrigger animation paths: reviewer's own conclusion was
"no fix unless profiler shows it".
- #32 Process.Start as Admin: would require explorer-token-drop
machinery; deferred (a click-once-per-session UX paper-cut).
- #36, #41, #44, #48, #53, #54, #57: reviewer confirmed not bugs.
- #40 RescanRequested via constructor: reviewer's "not a bug today".
- #43 AllowsTransparency: acceptable trade-off for confirm dialogs.
- #45, #46 manifest version: cosmetic.
- #47 Inno [Files] precondition: release-script concern, not
shipped product.
- #55, #56: minor UX nits.
- #58 CrashLog.Write return success/failure: would change the
signature across every caller; out of scope for a fixup pass.
178/178 tests passed before this commit; running on Windows after.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
FarmLox
added a commit
that referenced
this pull request
May 5, 2026
…odeql-action-4 chore(deps): bump github/codeql-action from 3 to 4
FarmLox
added a commit
that referenced
this pull request
May 5, 2026
Addresses every actionable finding from the independent ship-readiness
review at non-repo-files/v1.5.4-ship-readiness-review.md. Findings
that the review flagged but explicitly did not fix here are documented
inline with their reasoning.
Native interop (latent UB; harmless on x64 by ABI luck):
- SHFILEOPSTRUCT: Pack=8 -> Pack=1 to match the Windows SDK's
pshpack1.h declaration. Pack=8 inserted 4 bytes of padding before
pFrom on x64, putting the C# field at offset 16 while the kernel
reads from offset 12 - the shell happened to read field-aligned
bytes that just so happened to look right.
- MSIHANDLE: changed from IntPtr (8 bytes on x64) to uint (4 bytes,
matching `typedef unsigned long MSIHANDLE` in msi.h). The IntPtr
signature would crash on x86 where the calling convention pushes
8 bytes for a 4-byte argument. Cascaded the type change through
Msi.cs and MsiFileInfoService.cs.
- X509Certificate.CreateFromSignedFile result is now disposed too
(was leaked until finalisation; the X509Certificate2 wrapper
duplicates the handle so the inner needs its own using).
Operation correctness:
- F5 keybinding (and any other Re-scan trigger) now gates on
Cleanup.IsOperating and Completion.IsComplete via a new
ScanViewModel.IsExternallyBlocked flag flipped from MainViewModel.
Without this, F5 during a Move started a parallel scan that raced
the active operation.
- EnumeratePatches now throws InvalidOperationException after
MaxConsecutiveNonSuccess just like EnumerateProducts does. The
silent break would have left real-but-superseded patches missing
from the result set, classifying them as orphaned and offering
them for cleanup.
- EnumeratePatches now Array.Clear's its GUID buffers between
iterations, matching EnumerateProducts.
- Pre-flight write probe in CleanupViewModel.MoveAllAsync is now
cancellable: the operationCts is created BEFORE the probe (was
after), so the Cancel button on the operating overlay actually
cancels rather than waiting out the SMB timeout. The probe also
goes through the injected IFileSystem so MockFileSystem-driven
tests don't hit real disk.
- Settings file lost-update race fixed: SaveAfterDelayAsync re-loads
before saving, copies MoveDestination onto the freshly-loaded
AppSettings, then writes. Previously, the cached _settings instance
could clobber updates the detail-window code-behinds wrote
(window-size persistence) while the user was typing in the move-
destination textbox.
- PruneEmptySubdirectories called with CancellationToken.None: best-
effort cleanup, not an operation the user's Cancel should
re-classify a successful Move/Delete as cancelled.
- Move/DeleteFailed status pill now also includes the crash log path,
so users can find detail rather than guess where to look.
- Maximize/Restore button glyph now updates with the window state.
Path leakage under elevation:
- DescribeWriteFailure no longer routes ex.Message into the dialog.
Even an IOException's .Message can carry paths from outside the
user's typed destination (lock-holder process paths, NTFS
resolution chains); under elevation those could be paths from
another user's profile. Caller now writes to crash log first,
passes the log path through DescribeWriteFailure, and the dialog
body shows only the user's own dest plus the log-path pointer.
Resx patterns updated; matching tests inverted.
- ScanViewModel generic-exception catch shows a dialog (was status
pill only, easily missed).
- DispatcherUnhandledException in App.xaml.cs guards against re-
entry: a second exception during the MessageBox's nested message
pump no longer stacks two dialogs / two log entries.
CLI:
- Rejects extra positional args for /s, /d (silent truncation
before); /m allows args[1] only.
- /m PATH path with unquoted spaces ("/m D:\My Backup") used to
become "D:\My" with no warning.
- Three-state exit code: 0 success, 2 partial success, 1 full
failure. Documented in --help. Sysadmin retry policies can now
distinguish "all files failed" from "1 of 100 failed".
- DeletingFiles / MovingFiles status messages take a pluralised
noun parameter so "1 files" is no longer printed for single-
orphan runs.
- Console.CancelKeyPress handler registered BEFORE the mutex
acquisition so a Ctrl+C in the gap prints "Cancelling..."
gracefully.
- Pre-mutex-cancel path also unhooks the cancel handler before
return, matching the post-finally cleanup.
Threading / state:
- ScanViewModel re-samples HasPendingReboot AFTER the scan await,
not before. Sampling before could publish a stale "no pending
reboot" if Windows Update queued a reboot during a multi-second
scan, allowing Move/Delete to enable on stale state.
- PropertyChanged-based MoveDestination binding (was LostFocus): the
400 ms debounce now actually earns its keep (per-keystroke updates
let the placeholder hide on the first character and the Move
button enable as soon as the path becomes non-empty), and the
debounce prevents save thrashing.
- MoveAllAsync uses the captured `dest` consistently (was reading
MoveDestination live for confirmation / move call / restore-hint
string), closing a race where a fast user could change the
textbox between IsInstallerFolderOrChild validation and the Move
service call.
Localisation:
- Strings.en-GB.resx deleted: it was a 1:1 duplicate of the neutral
resx, and the project's NeutralLanguage is en-GB so .NET fallback
already returned the neutral resource for en-GB consumers. The
satellite assembly was loaded but its content was identical.
Maintenance trap eliminated.
- Resx patterns added: Cli.Help.ExitCodes* (the new --help block),
Cli.PendingRebootBlocked, Cli.EventLogPendingRebootBlocked.
UX polish:
- Result overlay tab-cycles inside the overlay's two buttons (was
cycling through main-window buttons behind the overlay until
focus eventually landed on Close).
- Result overlay has a 1px slate border so it reads as a layered
window instead of a free-floating block.
- Click on the dim margin around the result overlay dismisses it.
- Maximize/Restore button glyph swaps between U+25A1 and U+2750.
- Result-screen errors block is now keyboard-focusable so screen
readers can read it (overrides SelectableText style's
IsTabStop=False locally).
- AboutWindow Close button gets AutomationProperties.Name (was
inconsistent with the four other windows' close buttons).
- SubtleLink hyperlinks now underline on hover so the link is
discoverable without relying on colour shift alone.
Tests:
- DescribeWriteFailureTests: inverted to assert the inner exception
message does NOT leak and the log path DOES surface.
- MainViewModelTests timing-coupled debounce wait now reads
CleanupViewModel.MoveDestinationSaveDelay (made internal)
instead of hardcoding 700 ms.
- OrphanedFilesViewModelTests dispose-cancel test uses
TaskCompletionSource (await-based) instead of
DateTime.UtcNow polling.
- PendingRebootServiceTests removed the tautological
Assert.IsType<bool>(svc.HasPendingReboot()) test.
- PruneEmptySubdirectoriesTests gated on the
INSTALLERCLEAN_TEST_PRUNE=1 env var so they don't delete real
installer-folder subdirs on dev/CI hosts.
- InstallerClean.Tests.csproj sets RestorePackagesWithLockFile=true
so test dependency drift can't mask production behaviour.
CLAUDE.md / MEMORY.md drift:
- CLAUDE.md said neutral resx is en-US; actually en-GB. Fixed and
noted the en-GB.resx satellite removal.
- CLAUDE.md said only Core has SupportedOSPlatform; CLI has it too.
Now mentions both.
- "Nothing currently blocking" replaced with a pointer to the latest
ship-readiness review.
- MEMORY.md "no ex.Message to UI" claim qualified with the documented
inline exceptions (DescribeWriteFailure, ScanViewModel's
InvalidOperationException catch).
Findings explicitly NOT actioned (with reasoning):
- #18, #25, #59 are duplicates of #1, #11.
- #31 EventTrigger animation paths: reviewer's own conclusion was
"no fix unless profiler shows it".
- #32 Process.Start as Admin: would require explorer-token-drop
machinery; deferred (a click-once-per-session UX paper-cut).
- #36, #41, #44, #48, #53, #54, #57: reviewer confirmed not bugs.
- #40 RescanRequested via constructor: reviewer's "not a bug today".
- #43 AllowsTransparency: acceptable trade-off for confirm dialogs.
- #45, #46 manifest version: cosmetic.
- #47 Inno [Files] precondition: release-script concern, not
shipped product.
- #55, #56: minor UX nits.
- #58 CrashLog.Write return success/failure: would change the
signature across every caller; out of scope for a fixup pass.
178/178 tests passed before this commit; running on Windows after.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
FarmLox
added a commit
that referenced
this pull request
May 11, 2026
Closes the wontfix sentinel from the r4 review (ux-findings.md #1 and #3). The Check-for-updates button has been silent during its ~8-second in-flight wait since v1.5.0 and the r3 cooldown extended that silence by another 5 seconds; users on the failure path saw a dim button with no explanation and read it as broken. Screen- reader users got nothing at all. Two new resx strings: UpdateCheck.Status.Checking = "Checking..." UpdateCheck.Status.JustChecked = "Just checked." New TextBlock next to the Check-for-updates button in About, muted body type, AutomationProperties.LiveSetting=Polite so Narrator / NVDA / JAWS announce the transitions. State transitions in AboutWindow.xaml.cs CheckNowClick: click -> "Checking..." result dialog -> (unchanged; user reads MessageBox) dialog dismiss -> "Just checked." cooldown end -> "" OperationCanceledException from CheckAsync (token cancel on rapid re-click or window close) bypasses the transition assignments, so the status returns to "Checking..." until the cooldown finally block clears it. Acceptable: a cancel-during-check user is the same user who clicked again, which is the path the cooldown is gating against. Resx Designer.cs regenerated. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
FarmLox
added a commit
that referenced
this pull request
Jul 19, 2026
…odeql-action-4 chore(deps): bump github/codeql-action from 3 to 4
FarmLox
added a commit
that referenced
this pull request
Jul 19, 2026
Addresses every actionable finding from the independent ship-readiness
review at non-repo-files/v1.5.4-ship-readiness-review.md. Findings
that the review flagged but explicitly did not fix here are documented
inline with their reasoning.
Native interop (latent UB; harmless on x64 by ABI luck):
- SHFILEOPSTRUCT: Pack=8 -> Pack=1 to match the Windows SDK's
pshpack1.h declaration. Pack=8 inserted 4 bytes of padding before
pFrom on x64, putting the C# field at offset 16 while the kernel
reads from offset 12 - the shell happened to read field-aligned
bytes that just so happened to look right.
- MSIHANDLE: changed from IntPtr (8 bytes on x64) to uint (4 bytes,
matching `typedef unsigned long MSIHANDLE` in msi.h). The IntPtr
signature would crash on x86 where the calling convention pushes
8 bytes for a 4-byte argument. Cascaded the type change through
Msi.cs and MsiFileInfoService.cs.
- X509Certificate.CreateFromSignedFile result is now disposed too
(was leaked until finalisation; the X509Certificate2 wrapper
duplicates the handle so the inner needs its own using).
Operation correctness:
- F5 keybinding (and any other Re-scan trigger) now gates on
Cleanup.IsOperating and Completion.IsComplete via a new
ScanViewModel.IsExternallyBlocked flag flipped from MainViewModel.
Without this, F5 during a Move started a parallel scan that raced
the active operation.
- EnumeratePatches now throws InvalidOperationException after
MaxConsecutiveNonSuccess just like EnumerateProducts does. The
silent break would have left real-but-superseded patches missing
from the result set, classifying them as orphaned and offering
them for cleanup.
- EnumeratePatches now Array.Clear's its GUID buffers between
iterations, matching EnumerateProducts.
- Pre-flight write probe in CleanupViewModel.MoveAllAsync is now
cancellable: the operationCts is created BEFORE the probe (was
after), so the Cancel button on the operating overlay actually
cancels rather than waiting out the SMB timeout. The probe also
goes through the injected IFileSystem so MockFileSystem-driven
tests don't hit real disk.
- Settings file lost-update race fixed: SaveAfterDelayAsync re-loads
before saving, copies MoveDestination onto the freshly-loaded
AppSettings, then writes. Previously, the cached _settings instance
could clobber updates the detail-window code-behinds wrote
(window-size persistence) while the user was typing in the move-
destination textbox.
- PruneEmptySubdirectories called with CancellationToken.None: best-
effort cleanup, not an operation the user's Cancel should
re-classify a successful Move/Delete as cancelled.
- Move/DeleteFailed status pill now also includes the crash log path,
so users can find detail rather than guess where to look.
- Maximize/Restore button glyph now updates with the window state.
Path leakage under elevation:
- DescribeWriteFailure no longer routes ex.Message into the dialog.
Even an IOException's .Message can carry paths from outside the
user's typed destination (lock-holder process paths, NTFS
resolution chains); under elevation those could be paths from
another user's profile. Caller now writes to crash log first,
passes the log path through DescribeWriteFailure, and the dialog
body shows only the user's own dest plus the log-path pointer.
Resx patterns updated; matching tests inverted.
- ScanViewModel generic-exception catch shows a dialog (was status
pill only, easily missed).
- DispatcherUnhandledException in App.xaml.cs guards against re-
entry: a second exception during the MessageBox's nested message
pump no longer stacks two dialogs / two log entries.
CLI:
- Rejects extra positional args for /s, /d (silent truncation
before); /m allows args[1] only.
- /m PATH path with unquoted spaces ("/m D:\My Backup") used to
become "D:\My" with no warning.
- Three-state exit code: 0 success, 2 partial success, 1 full
failure. Documented in --help. Sysadmin retry policies can now
distinguish "all files failed" from "1 of 100 failed".
- DeletingFiles / MovingFiles status messages take a pluralised
noun parameter so "1 files" is no longer printed for single-
orphan runs.
- Console.CancelKeyPress handler registered BEFORE the mutex
acquisition so a Ctrl+C in the gap prints "Cancelling..."
gracefully.
- Pre-mutex-cancel path also unhooks the cancel handler before
return, matching the post-finally cleanup.
Threading / state:
- ScanViewModel re-samples HasPendingReboot AFTER the scan await,
not before. Sampling before could publish a stale "no pending
reboot" if Windows Update queued a reboot during a multi-second
scan, allowing Move/Delete to enable on stale state.
- PropertyChanged-based MoveDestination binding (was LostFocus): the
400 ms debounce now actually earns its keep (per-keystroke updates
let the placeholder hide on the first character and the Move
button enable as soon as the path becomes non-empty), and the
debounce prevents save thrashing.
- MoveAllAsync uses the captured `dest` consistently (was reading
MoveDestination live for confirmation / move call / restore-hint
string), closing a race where a fast user could change the
textbox between IsInstallerFolderOrChild validation and the Move
service call.
Localisation:
- Strings.en-GB.resx deleted: it was a 1:1 duplicate of the neutral
resx, and the project's NeutralLanguage is en-GB so .NET fallback
already returned the neutral resource for en-GB consumers. The
satellite assembly was loaded but its content was identical.
Maintenance trap eliminated.
- Resx patterns added: Cli.Help.ExitCodes* (the new --help block),
Cli.PendingRebootBlocked, Cli.EventLogPendingRebootBlocked.
UX polish:
- Result overlay tab-cycles inside the overlay's two buttons (was
cycling through main-window buttons behind the overlay until
focus eventually landed on Close).
- Result overlay has a 1px slate border so it reads as a layered
window instead of a free-floating block.
- Click on the dim margin around the result overlay dismisses it.
- Maximize/Restore button glyph swaps between U+25A1 and U+2750.
- Result-screen errors block is now keyboard-focusable so screen
readers can read it (overrides SelectableText style's
IsTabStop=False locally).
- AboutWindow Close button gets AutomationProperties.Name (was
inconsistent with the four other windows' close buttons).
- SubtleLink hyperlinks now underline on hover so the link is
discoverable without relying on colour shift alone.
Tests:
- DescribeWriteFailureTests: inverted to assert the inner exception
message does NOT leak and the log path DOES surface.
- MainViewModelTests timing-coupled debounce wait now reads
CleanupViewModel.MoveDestinationSaveDelay (made internal)
instead of hardcoding 700 ms.
- OrphanedFilesViewModelTests dispose-cancel test uses
TaskCompletionSource (await-based) instead of
DateTime.UtcNow polling.
- PendingRebootServiceTests removed the tautological
Assert.IsType<bool>(svc.HasPendingReboot()) test.
- PruneEmptySubdirectoriesTests gated on the
INSTALLERCLEAN_TEST_PRUNE=1 env var so they don't delete real
installer-folder subdirs on dev/CI hosts.
- InstallerClean.Tests.csproj sets RestorePackagesWithLockFile=true
so test dependency drift can't mask production behaviour.
Project notes drift:
- The notes said neutral resx is en-US; actually en-GB. Fixed and
noted the en-GB.resx satellite removal.
- The notes said only Core has SupportedOSPlatform; CLI has it too.
Now mentions both.
- "Nothing currently blocking" replaced with a pointer to the latest
ship-readiness review.
- MEMORY.md "no ex.Message to UI" claim qualified with the documented
inline exceptions (DescribeWriteFailure, ScanViewModel's
InvalidOperationException catch).
Findings explicitly NOT actioned (with reasoning):
- #18, #25, #59 are duplicates of #1, #11.
- #31 EventTrigger animation paths: reviewer's own conclusion was
"no fix unless profiler shows it".
- #32 Process.Start as Admin: would require explorer-token-drop
machinery; deferred (a click-once-per-session UX paper-cut).
- #36, #41, #44, #48, #53, #54, #57: reviewer confirmed not bugs.
- #40 RescanRequested via constructor: reviewer's "not a bug today".
- #43 AllowsTransparency: acceptable trade-off for confirm dialogs.
- #45, #46 manifest version: cosmetic.
- #47 Inno [Files] precondition: release-script concern, not
shipped product.
- #55, #56: minor UX nits.
- #58 CrashLog.Write return success/failure: would change the
signature across every caller; out of scope for a fixup pass.
178/178 tests passed before this commit; running on Windows after.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
FarmLox
added a commit
that referenced
this pull request
Jul 19, 2026
Closes the wontfix sentinel from the r4 review (ux-findings.md #1 and #3). The Check-for-updates button has been silent during its ~8-second in-flight wait since v1.5.0 and the r3 cooldown extended that silence by another 5 seconds; users on the failure path saw a dim button with no explanation and read it as broken. Screen- reader users got nothing at all. Two new resx strings: UpdateCheck.Status.Checking = "Checking..." UpdateCheck.Status.JustChecked = "Just checked." New TextBlock next to the Check-for-updates button in About, muted body type, AutomationProperties.LiveSetting=Polite so Narrator / NVDA / JAWS announce the transitions. State transitions in AboutWindow.xaml.cs CheckNowClick: click -> "Checking..." result dialog -> (unchanged; user reads MessageBox) dialog dismiss -> "Just checked." cooldown end -> "" OperationCanceledException from CheckAsync (token cancel on rapid re-click or window close) bypasses the transition assignments, so the status returns to "Checking..." until the cooldown finally block clears it. Acceptable: a cancel-during-check user is the same user who clicked again, which is the path the cooldown is gating against. Resx Designer.cs regenerated. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Bumps github/codeql-action from 3 to 4.
Release notes
Sourced from github/codeql-action's releases.
... (truncated)
Changelog
Sourced from github/codeql-action's changelog.
... (truncated)
Commits
5cc552fMerge pull request #3768 from github/dependabot/npm_and_yarn/npm-minor-3536e7...6b1a9f2Merge branch 'main' into dependabot/npm_and_yarn/npm-minor-3536e7c6f09d3ec57Merge pull request #3770 from github/dependabot/github_actions/dot-github/wor...3ff82aaMerge pull request #3575 from github/mbg/ts/sync-checks4bdd4e7Merge pull request #3554 from github/sam-robson/overlay-include-diff23a0098fix: improve error handling and logging for diff range path resolutionea7b090Rebuilda663d01Bump ruby/setup-rubyb659882Bump the npm-minor group with 5 updatesd5bb39frefactor: single source of truth for getDiffRangesJsonFilePath and simplified...Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting
@dependabot rebase.Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR:
@dependabot rebasewill rebase this PR@dependabot recreatewill recreate this PR, overwriting any edits that have been made to it@dependabot show <dependency name> ignore conditionswill show all of the ignore conditions of the specified dependency@dependabot ignore this major versionwill close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)@dependabot ignore this minor versionwill close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)@dependabot ignore this dependencywill close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)