Skip to content

chore(deps): bump github/codeql-action from 3 to 4#1

Merged
FarmLox merged 1 commit into
mainfrom
dependabot/github_actions/github/codeql-action-4
Apr 4, 2026
Merged

chore(deps): bump github/codeql-action from 3 to 4#1
FarmLox merged 1 commit into
mainfrom
dependabot/github_actions/github/codeql-action-4

Conversation

@dependabot

@dependabot dependabot Bot commented on behalf of github Mar 30, 2026

Copy link
Copy Markdown
Contributor

Bumps github/codeql-action from 3 to 4.

Release notes

Sourced from github/codeql-action's releases.

v3.35.1

v3.35.0

v3.34.1

  • Downgrade default CodeQL bundle version to 2.24.3 due to issues with a small percentage of Actions and JavaScript analyses. #3762

v3.34.0

  • Added an experimental change which disables TRAP caching when improved incremental analysis is enabled, since improved incremental analysis supersedes TRAP caching. This will improve performance and reduce Actions cache usage. We expect to roll this change out to everyone in March. #3569
  • We are rolling out improved incremental analysis to C/C++ analyses that use build mode none. We expect this rollout to be complete by the end of April 2026. #3584
  • Update default CodeQL bundle version to 2.25.0. #3585

v3.33.0

  • Upcoming change: Starting April 2026, the CodeQL Action will skip collecting file coverage information on pull requests to improve analysis performance. File coverage information will still be computed on non-PR analyses. Pull request analyses will log a warning about this upcoming change. #3562 To opt out of this change:
    • Repositories owned by an organization: Create a custom repository property with the name github-codeql-file-coverage-on-prs and the type "True/false", then set this property to true in the repository's settings. For more information, see Managing custom properties for repositories in your organization. Alternatively, if you are using an advanced setup workflow, you can set the CODEQL_ACTION_FILE_COVERAGE_ON_PRS environment variable to true in your workflow.
    • User-owned repositories using default setup: Switch to an advanced setup workflow and set the CODEQL_ACTION_FILE_COVERAGE_ON_PRS environment variable to true in your workflow.
    • User-owned repositories using advanced setup: Set the CODEQL_ACTION_FILE_COVERAGE_ON_PRS environment variable to true in your workflow.
  • Fixed a bug which caused the CodeQL Action to fail loading repository properties if a "Multi select" repository property was configured for the repository. #3557
  • The CodeQL Action now loads custom repository properties on GitHub Enterprise Server, enabling the customization of features such as github-codeql-disable-overlay that was previously only available on GitHub.com. #3559
  • Once private package registries can be configured with OIDC-based authentication for organizations, the CodeQL Action will now be able to accept such configurations. #3563
  • Fixed the retry mechanism for database uploads. Previously this would fail with the error "Response body object should not be disturbed or locked". #3564
  • A warning is now emitted if the CodeQL Action detects a repository property whose name suggests that it relates to the CodeQL Action, but which is not one of the properties recognised by the current version of the CodeQL Action. #3570

v3.32.6

  • Update default CodeQL bundle version to 2.24.3. #3548

v3.32.5

  • Repositories owned by an organization can now set up the github-codeql-disable-overlay custom repository property to disable improved incremental analysis for CodeQL. First, create a custom repository property with the name github-codeql-disable-overlay and the type "True/false" in the organization's settings. Then in the repository's settings, set this property to true to disable improved incremental analysis. For more information, see Managing custom properties for repositories in your organization. This feature is not yet available on GitHub Enterprise Server. #3507
  • Added an experimental change so that when improved incremental analysis fails on a runner — potentially due to insufficient disk space — the failure is recorded in the Actions cache so that subsequent runs will automatically skip improved incremental analysis until something changes (e.g. a larger runner is provisioned or a new CodeQL version is released). We expect to roll this change out to everyone in March. #3487
  • The minimum memory check for improved incremental analysis is now skipped for CodeQL 2.24.3 and later, which has reduced peak RAM usage. #3515
  • Reduced log levels for best-effort private package registry connection check failures to reduce noise from workflow annotations. #3516
  • Added an experimental change which lowers the minimum disk space requirement for improved incremental analysis, enabling it to run on standard GitHub Actions runners. We expect to roll this change out to everyone in March. #3498
  • Added an experimental change which allows the start-proxy action to resolve the CodeQL CLI version from feature flags instead of using the linked CLI bundle version. We expect to roll this change out to everyone in March. #3512
  • The previously experimental changes from versions 4.32.3, 4.32.4, 3.32.3 and 3.32.4 are now enabled by default. #3503, #3504

v3.32.4

  • Update default CodeQL bundle version to 2.24.2. #3493
  • Added an experimental change which improves how certificates are generated for the authentication proxy that is used by the CodeQL Action in Default Setup when private package registries are configured. This is expected to generate more widely compatible certificates and should have no impact on analyses which are working correctly already. We expect to roll this change out to everyone in February. #3473
  • When the CodeQL Action is run with debugging enabled in Default Setup and private package registries are configured, the "Setup proxy for registries" step will output additional diagnostic information that can be used for troubleshooting. #3486
  • Added a setting which allows the CodeQL Action to enable network debugging for Java programs. This will help GitHub staff support customers with troubleshooting issues in GitHub-managed CodeQL workflows, such as Default Setup. This setting can only be enabled by GitHub staff. #3485
  • Added a setting which enables GitHub-managed workflows, such as Default Setup, to use a nightly CodeQL CLI release instead of the latest, stable release that is used by default. This will help GitHub staff support customers whose analyses for a given repository or organization require early access to a change in an upcoming CodeQL CLI release. This setting can only be enabled by GitHub staff. #3484

v3.32.3

  • Added experimental support for testing connections to private package registries. This feature is not currently enabled for any analysis. In the future, it may be enabled by default for Default Setup. #3466

v3.32.2

... (truncated)

Changelog

Sourced from github/codeql-action's changelog.

4.32.3 - 13 Feb 2026

  • Added experimental support for testing connections to private package registries. This feature is not currently enabled for any analysis. In the future, it may be enabled by default for Default Setup. #3466

4.32.2 - 05 Feb 2026

  • Update default CodeQL bundle version to 2.24.1. #3460

4.32.1 - 02 Feb 2026

  • A warning is now shown in Default Setup workflow logs if a private package registry is configured using a GitHub Personal Access Token (PAT), but no username is configured. #3422
  • Fixed a bug which caused the CodeQL Action to fail when repository properties cannot successfully be retrieved. #3421

4.32.0 - 26 Jan 2026

  • Update default CodeQL bundle version to 2.24.0. #3425

4.31.11 - 23 Jan 2026

  • When running a Default Setup workflow with Actions debugging enabled, the CodeQL Action will now use more unique names when uploading logs from the Dependabot authentication proxy as workflow artifacts. This ensures that the artifact names do not clash between multiple jobs in a build matrix. #3409
  • Improved error handling throughout the CodeQL Action. #3415
  • Added experimental support for automatically excluding generated files from the analysis. This feature is not currently enabled for any analysis. In the future, it may be enabled by default for some GitHub-managed analyses. #3318
  • The changelog extracts that are included with releases of the CodeQL Action are now shorter to avoid duplicated information from appearing in Dependabot PRs. #3403

4.31.10 - 12 Jan 2026

  • Update default CodeQL bundle version to 2.23.9. #3393

4.31.9 - 16 Dec 2025

No user facing changes.

4.31.8 - 11 Dec 2025

  • Update default CodeQL bundle version to 2.23.8. #3354

4.31.7 - 05 Dec 2025

  • Update default CodeQL bundle version to 2.23.7. #3343

4.31.6 - 01 Dec 2025

No user facing changes.

4.31.5 - 24 Nov 2025

  • Update default CodeQL bundle version to 2.23.6. #3321

4.31.4 - 18 Nov 2025

... (truncated)

Commits
  • 5cc552f Merge pull request #3768 from github/dependabot/npm_and_yarn/npm-minor-3536e7...
  • 6b1a9f2 Merge branch 'main' into dependabot/npm_and_yarn/npm-minor-3536e7c6f0
  • 9d3ec57 Merge pull request #3770 from github/dependabot/github_actions/dot-github/wor...
  • 3ff82aa Merge pull request #3575 from github/mbg/ts/sync-checks
  • 4bdd4e7 Merge pull request #3554 from github/sam-robson/overlay-include-diff
  • 23a0098 fix: improve error handling and logging for diff range path resolution
  • ea7b090 Rebuild
  • a663d01 Bump ruby/setup-ruby
  • b659882 Bump the npm-minor group with 5 updates
  • d5bb39f refactor: single source of truth for getDiffRangesJsonFilePath and simplified...
  • Additional commits viewable in compare view

Dependabot compatibility score

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 rebase will rebase this PR
  • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
  • @dependabot show <dependency name> ignore conditions will show all of the ignore conditions of the specified dependency
  • @dependabot ignore this major version will 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 version will 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 dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)

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>
@dependabot dependabot Bot added dependencies Pull requests that update a dependency file github_actions Pull requests that update GitHub Actions code labels Mar 30, 2026
@FarmLox
FarmLox merged commit 4c4e9fc into main Apr 4, 2026
3 checks passed
@FarmLox
FarmLox deleted the dependabot/github_actions/github/codeql-action-4 branch April 4, 2026 04:47
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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dependencies Pull requests that update a dependency file github_actions Pull requests that update GitHub Actions code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant