#!/usr/bin/env python3
"""WinDevPilot - a quiet, account-aware Windows update manager.

The GUI discovers updates from several command-line package managers, lets the
user select exactly what to update, keeps user-scoped work in the launching
account context, and runs machine-scoped work directly when already elevated
or through one UAC elevation request when needed.

Runtime dependencies are deliberately limited to the Python standard library.
"""

from __future__ import annotations

import argparse
import array
import atexit
import concurrent.futures
import colorsys
import configparser
import contextlib
import ctypes
import dataclasses
import datetime as dt
import faulthandler
import functools
import heapq
import hashlib
import hmac
import html
import io
import ipaddress
import itertools
import json
import locale
import math
import os
import platform
import queue
import re
import shlex
import shutil
import stat
import struct
import subprocess
import sys
import tempfile
import threading
import time
import tomllib
import traceback
import urllib.error
import urllib.parse
import urllib.request
import uuid
import xml.etree.ElementTree as ET
import zipfile
import zlib
from abc import ABC, abstractmethod
from collections import Counter, OrderedDict, defaultdict, deque
from collections.abc import Callable, Iterable, Iterator, Mapping, MutableMapping, Sequence, Set
from multiprocessing.connection import Client, Listener
from pathlib import Path, PureWindowsPath
from typing import Any, ClassVar


APP_NAME = "WinDevPilot"
LEGACY_APP_DATA_NAME = "WinDevUpdates"
APP_VERSION = "1.3.28"
SHOWCASE_STARTUP = True  # Temporary showcase default; False restores normal view preferences.
MIN_PYTHON = (3, 12)
SCRIPT_PATH = Path(__file__).resolve()
CREATE_NO_WINDOW = 0x08000000 if os.name == "nt" else 0
BELOW_NORMAL_PRIORITY_CLASS = 0x00004000 if os.name == "nt" else 0
ANSI_RE = re.compile(r"\x1b(?:\[[0-?]*[ -/]*[@-~]|\][^\x07]*(?:\x07|\x1b\\))")
SAFE_PACKAGE_ID_RE = re.compile(r"^[A-Za-z0-9@][A-Za-z0-9@+._/-]*$")
SAFE_VCPKG_PACKAGE_RE = re.compile(
    r"^[A-Za-z0-9][A-Za-z0-9+._-]*(?::[A-Za-z0-9][A-Za-z0-9+._-]*)?$"
)
SAFE_VERSION_RE = re.compile(r"^[A-Za-z0-9][A-Za-z0-9!+._~-]*$")
SAFE_PROVIDER_SOURCE_RE = re.compile(r"^[A-Za-z0-9][A-Za-z0-9._-]*$")
STEAM_ARP_PACKAGE_ID_RE = re.compile(
    r"^ARP\\(?:Machine|User)\\(?:X64|X86)\\Steam App [1-9][0-9]*$",
    re.IGNORECASE,
)
SHA256_RE = re.compile(r"^[0-9a-f]{64}$")
MSI_PRODUCT_CODE_RE = re.compile(
    r"^\{[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-"
    r"[0-9A-Fa-f]{4}-[0-9A-Fa-f]{12}\}$"
)
WINGET_REBOOT_CODES = frozenset({1641, 3010, 0x8A150109, 0x8A15010B})
WINGET_ALREADY_CURRENT_CODES = frozenset({0x8A15004F, 0x8A15010D, 0x8A15010E})
WINGET_NO_APPLICATIONS_FOUND = 0x8A150014
WINGET_INTERNAL_ERROR = 0x8A150001
WINGET_INSTALLER_HASH_MISMATCH = 0x8A150011
WINGET_INSTALLED_FILE_HASH_MISMATCH = 0x8A150204
MSIX_PACKAGED_SERVICE_REQUIRES_ADMIN = 0x80073D28
WINGET_NOT_APPLICABLE_CODES = frozenset({0x8A150010, 0x8A15002B})
WINGET_CANCELED_CODES = frozenset({0x8A150005, 0x8A150077, 0x8A15010C})
WINGET_SUCCESS_CODES = frozenset({0, *WINGET_REBOOT_CODES})
WINGET_SCOPE_FAILURE_CODES = frozenset({0x8A150056, 0x8A15007D})
WINGET_RETRYABLE_FAILURE_CODES = frozenset(
    {
        1618,
        0x8A150008,
        0x8A150019,
        0x8A15002E,
        0x8A150045,
        0x8A15004B,
        0x8A15006B,
        0x8A15006D,
        0x8A150086,
        0x8A150101,
        0x8A150102,
        0x8A150103,
        0x8A150104,
        0x8A150105,
        0x8A150106,
        0x8A150107,
        0x8A15010A,
        0x8A150111,
    }
)
WINGET_SECURITY_FAILURE_CODES = frozenset({0x8A15002D, 0x8A15005E, 0x8A150060})
WINGET_MIGRATION_FAILURE_CODES = frozenset({0x8A15008E, 0x8A150114})
WINGET_NOTE_BY_CODE = {
    MSIX_PACKAGED_SERVICE_REQUIRES_ADMIN: (
        "an MSIX packaged service requires administrator privileges; review the app's "
        "supported updater/installer with administrator assistance for the owning account"
    ),
    1618: "another MSI installation is in progress; retry later",
    0x8A150008: "the installer download failed; check the network and retry",
    0x8A150010: "no installer applies to this system",
    WINGET_INSTALLER_HASH_MISMATCH: (
        "installer hash mismatch; the WinGet manifest may be catching up to a changed "
        "vendor download"
    ),
    WINGET_NO_APPLICATIONS_FOUND: "no matching installed package registration was found",
    0x8A150019: "this operation requires administrator privileges",
    0x8A15002B: ("the offered installer technology differs from the installed version"),
    0x8A15002D: "the installer failed WinGet's security check; do not bypass it",
    0x8A15002E: "the download size did not match the expected content length; retry later",
    0x8A15001B: "Microsoft Store is blocked by policy",
    0x8A15001C: "this Store app is blocked by policy",
    0x8A15003A: "the operation is blocked by Group Policy",
    0x8A150045: "WinGet could not open the package source",
    0x8A15004B: "WinGet could not open one or more package sources",
    0x8A150050: "the installed version is unknown and WinGet cannot choose an upgrade safely",
    0x8A150056: "the installer refuses an elevated context; run it as its owning user",
    0x8A15005E: "the server certificate did not match WinGet's pinned certificate",
    0x8A150060: "the archive failed WinGet's malware scan; do not bypass it",
    0x8A150068: "a WinGet pin prevents this upgrade",
    0x8A150069: "the installed package is a stub and needs vendor or Store servicing",
    0x8A15006B: "WinGet could not download package dependencies",
    0x8A15006D: "a required service is busy or unavailable; retry later",
    0x8A15007D: "an administrator context cannot modify this user-scoped package",
    0x8A150086: "WinGet downloaded a zero-byte installer; check the network",
    0x8A15008E: "the update uses a different install technology; review reinstall options",
    0x8A150101: "close the running application, then retry",
    0x8A150102: "another installation is in progress; retry later",
    0x8A150103: "a required file is in use; close the application, then retry",
    0x8A150104: "a required package dependency is missing",
    0x8A150105: "the destination disk is full; free space, then retry",
    0x8A150106: "available memory is insufficient; close other applications, then retry",
    0x8A150107: "this update requires network connectivity",
    0x8A15010A: "restart Windows, then retry this update",
    0x8A15010B: "the installer initiated a restart",
    0x8A15010F: "organizational policy prevents this installation",
    0x8A150111: "another application is using this package; close it, then retry",
    0x8A150114: "the installer cannot upgrade this installation; review migration options",
    0x8A150115: "the vendor installer returned a custom error; review its diagnostic log",
    WINGET_INSTALLED_FILE_HASH_MISMATCH: (
        "an existing installed file no longer matches WinGet's recorded hash; review or "
        "repair this installation"
    ),
}
MAX_ELEVATION_PLAN_BYTES = 1_000_000
MAX_ELEVATION_RECEIPT_BYTES = 25_000_000
MAX_ELEVATION_BATCH_ITEMS = 100
ELEVATION_TRANSPORT_TEST_OPERATION = "transport-test"
POWERSHELL_DISCOVERY_TIMEOUT_SECONDS = 600
ELEVATION_PIPE_RE = re.compile(rf"^\\\\\.\\pipe\\{APP_NAME}-[0-9a-f]{{32}}$", re.IGNORECASE)
MAX_DIAGNOSTIC_OUTPUT_CHARS = 200_000
DIAGNOSTIC_OUTPUT_HEAD_CHARS = 80_000
MAX_COMMAND_OUTPUT_BYTES = 16 * 1024 * 1024
ATOMIC_REPLACE_TRANSIENT_WINERRORS = frozenset({5, 32, 33})
ATOMIC_REPLACE_RETRY_DELAYS_SECONDS = (0.02, 0.05, 0.1)
COMMAND_OUTPUT_CHUNK_BYTES = 64 * 1024
MAX_RELATED_INSTALLER_LOGS = 4
MAX_RELATED_INSTALLER_LOG_READ_BYTES = 2_000_000
MAX_LOG_WIDGET_LINES = 4_000
MAX_LOG_LINE_CHARS = 4_000
MAX_ICON_INDEX_BYTES = 2_000_000
MAX_ICON_DECODE_PIXELS = 16_000_000
MAX_ICO_FILE_BYTES = 64 * 1024 * 1024
MAX_ICON_RENDER_MESSAGE_BYTES = 32_768
MAX_ICON_GALLERY_REQUEST_BYTES = 64 * 1024
MAX_ICON_GALLERY_RESULTS = 80
MAX_ICON_SHOWCASE_SIZE = 1536
MAX_ICON_SHOWCASE_WIRE_BYTES = 32 * 1024 * 1024
MAX_ICON_GALLERY_BUNDLE_BYTES = 128 * 1024 * 1024
MAX_ICON_GALLERY_IMAGE_BYTES = 32 * 1024 * 1024
ICON_GALLERY_WIRE_MAGIC = b"WDPIGW2\0"
AND_MASK_ALPHA_BYTES = tuple(
    bytes(0 if value & (0x80 >> bit) else 255 for bit in range(8))
    for value in range(256)
)
ICON_GALLERY_PREFETCH_MEMORY_RESERVE = 1 * 1024**3
ICON_GALLERY_PREFETCH_MEMORY_PER_PACKAGE = 4 * 1024**2
ICON_GALLERY_MEMORY_REPORT_START = 32 * 1024**2
ICON_GALLERY_BLIT_MEMORY_REPORT_START = 1 * 1024**2
ICON_GALLERY_BLIT_CACHE_MAX_BYTES = 1 * 1024**3
ICON_GALLERY_PHOTO_DECODE_TIME_BUDGET_SECONDS = 0.006
ICON_RENDER_JOB_TIMEOUT_SECONDS = 90.0
APP_ICON_CACHE_PREFIX = "appicon-v5-"
DETAIL_ICON_CACHE_PREFIX = "detailsicon-v6-"
RAW_ICON_CACHE_PREFIX = "rawicon-v1-"
DISPLAY_ICON_CACHE_PREFIX = "displayicon-v15-"
ICON_RESAMPLING_POLICY = "bilinear-v1"
PROVIDER_ICON_CACHE_PREFIX = "provider-minus-v1-"
VECTOR_ICON_CACHE_PREFIX = "vectoricon-v5-"
WINDOWS_ICON_EXTRACTION_REVISION = "native-alpha-v3"
UI_EVENT_BATCH_LIMIT = 64
UI_EVENT_TIME_BUDGET_SECONDS = 0.008
UI_EVENT_BACKLOG_DELAY_MS = 4
UI_EVENT_BUSY_DELAY_MS = 25
UI_EVENT_BACKGROUND_DELAY_MS = 32
UI_EVENT_IDLE_DELAY_MS = 100
WINDOW_DRAG_BUSY_ANIMATION_POLL_MS = 100
WINDOW_DRAG_THREAD_SWITCH_INTERVAL_SECONDS = 0.002
INDETERMINATE_PROGRESS_INTERVAL_MS = 50
WINDOWS_THEME_POLL_MS = 3000
ICON_RENDERER_WARM_DELAY_MS = 1500
WARM_ICON_CACHE_MIN_COUNT = 8
ICON_HYDRATION_PAINT_LIMIT = 10
ICON_HYDRATION_TIME_BUDGET_SECONDS = 0.006
ICON_SLICE_BUDGET_SECONDS = 0.012
ICON_KEY_RELEASE_SETTLE_MS = 55
ICON_BACKGROUND_SWEEP_DELAY_MS = 35
ICON_BACKGROUND_SWEEP_SCROLL_DELAY_MS = 360
ICON_BACKGROUND_PROGRESS_MS = 30_000
IDLE_DATE_SLEUTH_DELAY_MS = 1_500
ICON_RENDER_MISS_TTL_SECONDS = 7 * 24 * 60 * 60
ADAPTIVE_OUTLINE_REVISION = "edge-dominance-v2"
ICON_EXTRACTION_POLICY_REVISION = "visible-alpha-core-v4"
ICON_SOURCE_SELECTION_REVISION = "nearby-artwork-v7"
_STEAM_SHELL_ICON_EXECUTABLES = {'753640': 'OuterWilds.exe', '294100': 'RimWorldWin64.exe',
                                 '890720': 'In Other Waters.exe'}
_SHELL_PREFERRED_ICON_NAMES = frozenset(name.casefold() for name in _STEAM_SHELL_ICON_EXECUTABLES.values())
ICON_GALLERY_POLICY_REVISION = "raw-memory-bundle-v6-shared-vectors"
ICON_CATALOG_SCHEMA = 1
ICON_CATALOG_FILENAME = "icon-catalog-v1.json"
ICON_CATALOG_MAX_BYTES = 8 * 1024 * 1024
ICON_CATALOG_BLOB_BUDGET_BYTES = 256 * 1024 * 1024
ICON_CATALOG_SINGLE_BLOB_MAX_BYTES = 4 * 1024 * 1024
ICON_PACK_MAGIC = b"WDPICONPACK\x03"
COMPACT_ICON_REVISION = "display-nn-center-5of8-v1"
ICON_CATALOG_NEGATIVE_SOURCE_TTL_SECONDS = 7 * 24 * 60 * 60
ICON_CATALOG_MAX_ENTRIES = 5000
PORTABLE_PROVIDER_KEY = "portable"
MICROSOFT_STORE_PROVIDER_KEY = "msstore"
MICROSOFT_STORE_SOURCE = "msstore"
MICROSOFT_STORE_UPDATES_URI = "ms-windows-store://downloadsandupdates"
MICROSOFT_STORE_PRODUCT_ID_RE = re.compile(r"^[A-Za-z0-9]{8,32}$")
PORTABLE_CACHE_SCHEMA = 2
PORTABLE_CACHE_FILENAME = "portable-inventory-v1.json"
PORTABLE_CACHE_MAX_BYTES = 4 * 1024 * 1024
PORTABLE_CACHE_MAX_ROOTS = 16
PORTABLE_CACHE_MAX_ITEMS = 5000
INSTALLED_INVENTORY_CACHE_SCHEMA = 5
INSTALLED_INVENTORY_CACHE_LEGACY_SCHEMAS = frozenset({1, 2, 3, 4})
INSTALLED_INVENTORY_CACHE_FILENAME = "installed-inventory-v1.json"
INSTALLED_INVENTORY_CACHE_MAX_BYTES = 8 * 1024 * 1024
INSTALLED_INVENTORY_CACHE_MAX_ITEMS = 10_000
INSTALLED_INVENTORY_CACHE_MAX_FIELD_CHARS = 65_536
SYSTEM_REPORT_MAX_BYTES = 16 * 1024 * 1024
SYSTEM_REPORT_COLUMNS = (
    "Name",
    "ID",
    "Installed",
    "Installed / serviced",
    "Provider",
    "Run as",
    "Status",
    "Installed folder",
    "Installed technology",
    "Installed size",
)
SYSTEM_REPORT_OPTIONAL_COLUMNS = frozenset(
    {"Installed / serviced", "Status", "Installed folder"}
)
SYSTEM_REPORT_INLINE_COLUMNS = ("Installed technology", "Installed size")
PORTABLE_SCAN_DIAGNOSTIC_SAMPLE_MAX = 24
# The portable scan budget is charged only for executable candidates. A much
# higher traversal fuse remains for pathological trees, while common dependency
# and build-intermediate directories are pruned before they consume it.
PORTABLE_SCAN_MAX_FILES = 25_000
PORTABLE_SCAN_MAX_DIRECTORIES = 200_000
PORTABLE_SCAN_MAX_METADATA_PROBES = 10_000
PORTABLE_SCAN_PROGRESS_INTERVAL_SECONDS = 20.0
_PORTABLE_INSTALLER_IDENTITY_RE = re.compile(
    r"(?i)(?:^|[^a-z])(setup|installer|uninstall(?:er)?|unins\d*|"
    r"updater?|firmware|driver|redist|vcredist|bootstrap|sfx|crashpad|"
    r"crashreporter?|helper)(?:[^a-z]|$)"
)
_PORTABLE_CONTENT_TREE_RE = re.compile(
    r"(?i)(?:\\|/)(steamapps|windowsapps|engine)(?:\\|/)"
)
_PORTABLE_COMPONENT_IDENTITY_RE = re.compile(
    r"(?i)(?:^|[^a-z])(plugin|registration service|wmi provider|"
    r"application ontology)(?:[^a-z]|$)"
)
_PORTABLE_HELPER_DESCRIPTION_RE = re.compile(
    r"(?i)(?:^|[^a-z])(setup|installer|uninstall(?:er)?|updater?|"
    r"bootstrap|helper)(?:[^a-z]|$)"
)
_PORTABLE_FILENAME_VERSION_RE = re.compile(r"(?<!\d)(\d+(?:\.\d+){1,3})(?!\d)")
_PORTABLE_AUXILIARY_STEM_RE = re.compile(
    r"(?:^|[._ -])(?:cli|console|tests?|benchmarks?|helper)(?:$|[._ -])"
)
PORTABLE_DATE_SLEUTH_MAX_SIBLINGS = 64
PORTABLE_DATE_SLEUTH_MAX_DIRECTORY_ENTRIES = 192
PORTABLE_DATE_SLEUTH_PAYLOAD_SUFFIXES = frozenset(
    {
        "",
        ".bin",
        ".cfg",
        ".config",
        ".dat",
        ".dll",
        ".exe",
        ".html",
        ".ico",
        ".ini",
        ".json",
        ".license",
        ".manifest",
        ".md",
        ".mui",
        ".pak",
        ".png",
        ".txt",
        ".xml",
    }
)
PORTABLE_CATALOG_REFRESH_TTL_SECONDS = 24 * 60 * 60
WINGET_ATTEMPT_STRATEGY_REVISION = 2
POST_UPDATE_PROVIDER_REUSE_GRACE_SECONDS = 3 * 60
PORTABLE_REMOVAL_MAX_ENTRIES = 4000
PORTABLE_STANDALONE_FILE_KEYS = frozenset({"cpu-z", "rufus", "chathy"})
PORTABLE_SHARED_FOLDER_NAMES = frozenset(
    {
        "app",
        "apps",
        "bin",
        "desktop",
        "documents",
        "downloads",
        "program",
        "programs",
        "portable",
        "portables",
        "tool",
        "tools",
        "utilities",
        "utility",
    }
)
PORTABLE_AMBIGUOUS_FOLDER_MARKERS = frozenset(
    {".git", ".hg", ".svn", ".venv", "node_modules", "venv"}
)
PORTABLE_HELPER_EXECUTABLE_STEMS = frozenset(
    {
        "crashpadhandler",
        "crashreport",
        "gup",
        "helper",
        "launcher",
        "unins",
        "uninstall",
        "update",
        "updater",
    }
)
DETAIL_ICON_MEMORY_LIMIT = 1024
DETAIL_ICON_MEMORY_BUDGET_BYTES = 48 * 1024 * 1024
PACKAGE_GALLERY_ICON_TIME_BUDGET_SECONDS = 0.008
PACKAGE_GALLERY_FIRST_PAINT_BUDGET_SECONDS = 0.016
PACKAGE_GALLERY_WHEEL_DECAY_SECONDS = 0.10
PACKAGE_GALLERY_COMPACT_SCALE = 5 / 8
ICON_IDLE_QUIET_MS = 300
ICON_IDLE_PROMOTION_INTERVAL_MS = 40
ICON_IDLE_TARGET_LIMIT = 128
ICON_IDLE_PROMOTION_TIME_BUDGET_SECONDS = 0.004
DETAIL_ICON_NAVIGATION_SETTLE_MS = 50
PROGRESS_TWEEN_SECONDS = 0.18
PROGRESS_TWEEN_INTERVAL_MS = 16
NOTIFICATION_WARNING_MS = 9000
UPDATE_REQUEST_CUE_MS = 450
NOTIFICATION_ERROR_MS = 12000
PRE_REDACTED_STRING_KEYS = frozenset({"output", "command"})
PRE_REDACTED_SEQUENCE_KEYS = frozenset({"requested_command"})
WINGET_INSTALLER_LOG_RE = re.compile(
    r"(?im)^\s*Installer log is available at:\s*(?P<path>.+?\.log)\s*$"
)
WINGET_CANONICAL_ACCESS_DENIED_RE = re.compile(
    r'(?is)weakly_canonical\s*:\s*Access is denied\.\s*:\s*"(?P<path>[^"\r\n]+)"'
)
WINGET_CHILD_INSTALLER_EXIT_RE = re.compile(
    r"(?im)^\s*Installer failed with exit code:\s*(?P<code>-?\d+)\s*$"
)
WINGET_SCOPE_MISMATCH_RE = re.compile(
    r"(?i)installer scope does not match currently installed scope:\s*"
    r"(?P<installer>machine|user)\s*!=\s*(?P<installed>machine|user)"
)
ELEVATION_PLAN_FIELDS = frozenset(
    {
        "provider",
        "name",
        "package_id",
        "current",
        "available",
        "source",
        "scope",
        "requires_admin",
        "instance",
    }
)
CLASS_SIMPLE_UPGRADE = "simple-upgrade"
CLASS_DUPLICATE_INSTALL = "duplicate-install"
CLASS_AMBIGUOUS_IDENTITY = "ambiguous-identity"
CLASS_SCOPE_UNKNOWN = "scope-unknown"
CLASS_VENDOR_MANAGED = "vendor-managed"
CLASS_SCOPE_OR_APPLICABILITY = "scope-or-applicability"
CLASS_MIGRATION_REQUIRED = "migration-required"
CLASS_RETRYABLE = "retryable"
CLASS_POLICY_BLOCKED = "policy-blocked"
CLASS_MANUAL_REPAIR = "manual-repair"
CLASS_MANIFEST_LAG = "manifest-lag"
CLASS_VERIFICATION_CONFLICT = "verification-conflict"
CLASS_MANUAL_REVIEW = "manual-review"
CLASS_INVENTORY_ONLY = "inventory-only"
KNOWN_CLASSIFICATIONS = frozenset(
    {
        CLASS_SIMPLE_UPGRADE,
        CLASS_DUPLICATE_INSTALL,
        CLASS_AMBIGUOUS_IDENTITY,
        CLASS_SCOPE_UNKNOWN,
        CLASS_VENDOR_MANAGED,
        CLASS_SCOPE_OR_APPLICABILITY,
        CLASS_MIGRATION_REQUIRED,
        CLASS_RETRYABLE,
        CLASS_POLICY_BLOCKED,
        CLASS_MANUAL_REPAIR,
        CLASS_MANIFEST_LAG,
        CLASS_VERIFICATION_CONFLICT,
        CLASS_MANUAL_REVIEW,
        CLASS_INVENTORY_ONLY,
    }
)
NON_BULK_CLASSIFICATIONS = KNOWN_CLASSIFICATIONS - {CLASS_SIMPLE_UPGRADE}
PREDICTION_ORDINARY = "ordinary"
PREDICTION_NOT_APPLICABLE = "not-applicable"
PREDICTION_MIGRATION_REQUIRED = "migration-required"
PREDICTION_VENDOR_MANAGED = "vendor-managed"
PREDICTION_DUPLICATE_RESOLUTION = "duplicate-resolution"
PREDICTION_STORE_AMBIGUOUS = "store-ambiguous"
PREDICTION_UNKNOWN = "unknown"
PREDICTION_PENDING = "pending"
PREDICTION_STALE = "stale"
PREDICTION_MANUAL_REPAIR = "manual-repair"
VALID_APPLICABILITY_PREDICTIONS = frozenset(
    {
        PREDICTION_ORDINARY,
        PREDICTION_NOT_APPLICABLE,
        PREDICTION_MIGRATION_REQUIRED,
        PREDICTION_VENDOR_MANAGED,
        PREDICTION_DUPLICATE_RESOLUTION,
        PREDICTION_STORE_AMBIGUOUS,
        PREDICTION_UNKNOWN,
        PREDICTION_PENDING,
        PREDICTION_STALE,
        PREDICTION_MANUAL_REPAIR,
    }
)
VALID_PREDICTION_CONFIDENCES = frozenset({"pending", "low", "medium", "high"})
WINGET_PACKAGE_POLICIES: dict[str, dict[str, Any]] = {
    "xp8bt8dw290mpq": {
        "classification": CLASS_VENDOR_MANAGED,
        "status": "Vendor-managed - update Microsoft Teams",
        "guidance": (
            "Microsoft Teams bundles and services its Teams Meeting Add-in. Update "
            "Teams instead of repeatedly forcing the ambiguous Store registration."
        ),
        "guidance_url": (
            "https://learn.microsoft.com/en-us/microsoftteams/teams-client-vdi-requirements-deploy"
        ),
        "suppress_bulk": True,
    },
    "microsoft.edge": {
        "classification": CLASS_VENDOR_MANAGED,
        "status": "Vendor-managed - Edge updates itself",
        "guidance": (
            "Microsoft Edge is a machine-scoped Microsoft browser with its own updater. "
            "Use Edge Settings > About Microsoft Edge or let Edge/Windows service it; "
            "WinGet attempts are best treated as diagnostic evidence."
        ),
        "guidance_url": "https://support.microsoft.com/microsoft-edge",
        "suppress_bulk": True,
    },
    "microsoft.gameinput": {
        "classification": CLASS_MANUAL_REVIEW,
        "status": "Windows component - review manually",
        "guidance": (
            "Microsoft GameInput is a small machine-scoped Windows/Microsoft gaming "
            "component serviced by Windows, Gaming Services, or Microsoft Store flows. "
            "WinDevPilot leaves it unchecked by default because direct WinGet updates "
            "often do not own the durable servicing path."
        ),
        "guidance_url": "https://learn.microsoft.com/gaming/gdk/docs/reference/input/gameinput/",
        "suppress_bulk": True,
    },
    "microsoft.powershell.preview": {
        "classification": CLASS_MIGRATION_REQUIRED,
        "status": "Needs migration",
        "guidance": (
            "PowerShell Preview has repeatedly appeared as an MSI-to-MSIX transition. "
            "Treat it as a guided migration candidate, not a normal silent WinGet upgrade."
        ),
        "guidance_url": "https://learn.microsoft.com/powershell/scripting/install/installing-powershell-on-windows",
        "suppress_bulk": True,
    },
}
BULK_SELECTION_REVIEW_STATUSES = frozenset(
    {
        "Ambiguous Store identity",
        "Duplicate user + machine installs",
        "Checking details…",
        "Needs different scope or installer",
        "Review - manifest unavailable",
        "Scope unknown",
        "Still offered after failed attempt",
        "Still offered after reported success",
        "Restart required to finish previous attempt",
        "Installed state changed after attempt - held",
    }
)
MAX_ATTEMPT_HOLDS = 200
MAX_RESTART_PENDING_MARKERS = 200
MAX_APPLICABILITY_HISTORY = 200
MAX_PACKAGE_HISTORY = 400
APPLICABILITY_HISTORY_THRESHOLD = 2
APPLICABILITY_HISTORY_TTL_DAYS = 120
BASE_DPI = 96
TK_POINTS_PER_INCH = 72
WINDOWS_11_BUILD = 22000
DPI_AWARENESS_CONTEXT_UNAWARE = -1
DPI_AWARENESS_CONTEXT_SYSTEM_AWARE = -2
DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE = -3
DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 = -4
DWMWA_WINDOW_CORNER_PREFERENCE = 33
DWMWA_USE_IMMERSIVE_DARK_MODE = 20
DWMWA_BORDER_COLOR = 34
DWMWA_CAPTION_COLOR = 35
DWMWA_TEXT_COLOR = 36
DWMWCP_DONOTROUND = 1
ERROR_ACCESS_DENIED = 5
ERROR_ALREADY_EXISTS = 183
ERROR_CANCELLED = 1223
WAIT_FAILED = 0xFFFFFFFF
WAIT_TIMEOUT = 0x00000102
LOG_SCHEMA_VERSION = 1
SETTINGS_SCHEMA_VERSION = 1
WINGET_RECENT_INVENTORY_TTL_SECONDS = 5.0
SCOOP_SOURCE_REFRESH_TTL_SECONDS = 10 * 60.0
SCOOP_SOURCE_REFRESH_TIMEOUT_SECONDS = 120.0
SESSION_LOG_RETENTION_BYTES = 64 * 1024 * 1024
SESSION_LOG_QUEUE_RECORD_LIMIT = 16_384
DIAGNOSTIC_CURRENT_LOG_MAX_CHARS = 1_000_000
DIAGNOSTIC_BUNDLE_MAX_BYTES = 32 * 1024 * 1024
TRANSIENT_OPERATION_STATUSES = frozenset(
    {
        "Queued",
        "Updating…",
        "Queued for administrator",
        "Uninstalling…",
    }
)
MAX_UI_PROCESS_OUTPUT_CHARS = 16_000
UPDATE_ROW_HEIGHT_DIP = 32
PROVIDER_ICON_COLUMN_WIDTH_DIP = 58
PROVIDER_ICON_COLUMN_MIN_WIDTH_DIP = 46
# Fill roughly 90% of each row: visibly larger than the former 26-DIP cell,
# while per-monitor DPI scaling preserves a small non-overlap gap everywhere.
PACKAGE_ICON_SIZE_DIP = round(UPDATE_ROW_HEIGHT_DIP * 0.90)
DETAIL_ICON_SIZE_DIP = 96
UPDATE_CHECKBOX_COLUMN_WIDTH_DIP = 56
UPDATE_CHECKBOX_COLUMN_MIN_WIDTH_DIP = 50
PROVIDER_TOGGLE_GLYPH_FONT = ("Segoe UI Symbol", 17)
SECONDARY_ACTIONS_GLYPH = "⛭"
CHECKED_GLYPH = "☑"
UNCHECKED_GLYPH = "☐"
# 64 KiB trades three integer multiplies/divides per translucent pixel for
# indexed C-built bytes. Opaque and transparent rows still take cheaper fast
# paths, so this table is used only where premultiplication is genuinely needed.
ALPHA_PREMULTIPLY_TABLES = tuple(
    bytes((channel * alpha + 127) // 255 for channel in range(256))
    for alpha in range(256)
)
TOOLTIP_DELAY_MS = 850
TOOLTIP_MOVE_TOLERANCE_PX = 10
SENSITIVE_ASSIGNMENT_RE = re.compile(
    r"(?i)(\b(?:[A-Za-z][A-Za-z0-9_-]*(?:api[-_]?key|access[-_]?key|auth[-_]?key|credential|"
    r"private[-_]?key|refresh[-_]?token|password|passwd|secret|token)|authorization|"
    r"cookie|pass(?:word|wd)?)\b\s*[:=]\s*)(?:\"[^\"]*\"|'[^']*'|[^\s,;]+)"
)
SENSITIVE_OPTION_RE = re.compile(
    r"(?i)(--(?:api[-_]?key|access[-_]?key|(?:elevated[-_])?auth[-_]?key|authorization|client[-_]?secret|cookie|"
    r"credential|password|private[-_]?key|refresh[-_]?token|secret|token)"
    r"(?:=|\s+))(?:\"[^\"]*\"|'[^']*'|\S+)"
)
SENSITIVE_OPTION_NAME_RE = re.compile(
    r"(?i)^--(?:api[-_]?key|access[-_]?key|(?:elevated[-_])?auth[-_]?key|authorization|client[-_]?secret|cookie|"
    r"credential|password|private[-_]?key|refresh[-_]?token|secret|token)$"
)
AUTH_SCHEME_RE = re.compile(r"(?i)\b(Bearer|Basic)\s+[A-Za-z0-9._~+/=-]+")
URL_USERINFO_RE = re.compile(r"(?i)(https?://)[^/\s:@]+:[^@\s/]+@")
REDACTION_TRIGGER_RE = re.compile(r"[\s\\/=:@]")
_INSTANCE_MUTEX: Any = None


# ==================== Windows bootstrap and shared failures ====================

class ElevationCancelled(RuntimeError):
    """The user dismissed the UAC credential prompt."""


@dataclasses.dataclass(frozen=True, slots=True)
class DpiBootstrapResult:
    requested: str
    active: str
    api: str
    changed: bool
    error: int | None = None

    def to_dict(self) -> dict[str, Any]:
        return {
            "requested": self.requested,
            "active": self.active,
            "api": self.api,
            "changed": self.changed,
            "error": self.error,
        }


@functools.cache
def windows_build() -> int:
    if os.name != "nt" or not hasattr(sys, "getwindowsversion"):
        return 0
    return int(sys.getwindowsversion().build)


@functools.lru_cache(maxsize=1)
def _user32() -> Any:
    user32 = ctypes.WinDLL("user32", use_last_error=True)
    user32.MessageBoxW.argtypes = [
        ctypes.c_void_p, ctypes.c_wchar_p, ctypes.c_wchar_p, ctypes.c_uint,
    ]
    user32.MessageBoxW.restype = ctypes.c_int
    return user32


def query_windows_dpi_awareness() -> str:
    """Return the current thread's effective Windows DPI-awareness context."""
    if os.name != "nt":
        return "not-windows"
    try:
        user32 = _user32()
        get_context = user32.GetThreadDpiAwarenessContext
        get_context.argtypes = []
        get_context.restype = ctypes.c_void_p
        are_equal = user32.AreDpiAwarenessContextsEqual
        are_equal.argtypes = [ctypes.c_void_p, ctypes.c_void_p]
        are_equal.restype = ctypes.c_int
        current = get_context()
        contexts = (
            ("per-monitor-v2", DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2),
            ("per-monitor", DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE),
            ("system", DPI_AWARENESS_CONTEXT_SYSTEM_AWARE),
            ("unaware", DPI_AWARENESS_CONTEXT_UNAWARE),
        )
        for label, value in contexts:
            if are_equal(current, ctypes.c_void_p(value)):
                return label
        return "unknown"
    except (AttributeError, OSError):
        return "unknown"


def configure_windows_dpi_awareness() -> DpiBootstrapResult:
    """Request PMv2 before Tk creates any HWND, with older-Windows fallbacks."""
    if os.name != "nt":
        return DpiBootstrapResult("per-monitor-v2", "not-windows", "none", False)

    error: int | None = None
    try:
        user32 = _user32()
        setter = user32.SetProcessDpiAwarenessContext
        setter.argtypes = [ctypes.c_void_p]
        setter.restype = ctypes.c_int
        ctypes.set_last_error(0)
        if setter(ctypes.c_void_p(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2)):
            return DpiBootstrapResult(
                "per-monitor-v2", query_windows_dpi_awareness(), "user32", True
            )
        error = ctypes.get_last_error() or None
        active = query_windows_dpi_awareness()
        if error == ERROR_ACCESS_DENIED:
            # A manifest or earlier host call already selected the process mode.
            return DpiBootstrapResult("per-monitor-v2", active, "preconfigured", False, error)
    except (AttributeError, OSError):
        pass

    # Windows 8.1/older Python fallback. This cannot request PMv2, but still
    # avoids DPI-unaware bitmap stretching on supported legacy systems.
    try:
        shcore = ctypes.WinDLL("shcore", use_last_error=True)
        set_awareness = shcore.SetProcessDpiAwareness
        set_awareness.argtypes = [ctypes.c_int]
        set_awareness.restype = ctypes.c_long
        result = int(set_awareness(2))  # PROCESS_PER_MONITOR_DPI_AWARE
        if result == 0:
            return DpiBootstrapResult(
                "per-monitor-v2", query_windows_dpi_awareness(), "shcore", True, error
            )
    except (AttributeError, OSError):
        pass

    try:
        legacy = _user32().SetProcessDPIAware
        legacy.argtypes = []
        legacy.restype = ctypes.c_int
        changed = bool(legacy())
        return DpiBootstrapResult(
            "per-monitor-v2",
            query_windows_dpi_awareness(),
            "user32-legacy",
            changed,
            error,
        )
    except (AttributeError, OSError):
        return DpiBootstrapResult(
            "per-monitor-v2", query_windows_dpi_awareness(), "unavailable", False, error
        )


def get_window_dpi(hwnd: int) -> int:
    if os.name != "nt" or not hwnd:
        return BASE_DPI
    try:
        get_dpi = _user32().GetDpiForWindow
        get_dpi.argtypes = [ctypes.c_void_p]
        get_dpi.restype = ctypes.c_uint
        dpi = int(get_dpi(ctypes.c_void_p(hwnd)))
        return dpi or BASE_DPI
    except (AttributeError, OSError):
        return BASE_DPI


def native_top_level_hwnd(hwnd: int) -> int:
    """Resolve Tk's client HWND to the DWM-owned wrapper HWND on Windows."""
    if os.name != "nt" or not hwnd:
        return hwnd
    try:
        get_ancestor = _user32().GetAncestor
        get_ancestor.argtypes = [ctypes.c_void_p, ctypes.c_uint]
        get_ancestor.restype = ctypes.c_void_p
        root_hwnd = get_ancestor(ctypes.c_void_p(hwnd), 2)  # GA_ROOT
        return int(root_hwnd) if root_hwnd else hwnd
    except (AttributeError, OSError):
        return hwnd


def dip_to_px(value: int | float, dpi: int) -> int:
    """Map a device-independent pixel to the nearest real integer pixel."""
    scaled = float(value) * max(BASE_DPI, int(dpi)) / BASE_DPI
    return math.floor(scaled + 0.5)


GEOMETRY_RE = re.compile(r"^(\d+)x(\d+)(?:([+-]\d+)([+-]\d+))?$")


def scale_geometry_spec(geometry: str, factor: float, *, scale_position: bool = False) -> str:
    """Scale a Tk geometry string while keeping every result on integer pixels."""
    match = GEOMETRY_RE.fullmatch(geometry.strip())
    if not match or not math.isfinite(factor) or factor <= 0:
        return geometry
    width_text, height_text, x_text, y_text = match.groups()

    def scaled(value: int) -> int:
        magnitude = math.floor(abs(value) * factor + 0.5)
        return -magnitude if value < 0 else magnitude

    width = max(1, scaled(int(width_text)))
    height = max(1, scaled(int(height_text)))
    result = f"{width}x{height}"
    if x_text is not None and y_text is not None:
        x = int(x_text)
        y = int(y_text)
        if scale_position:
            x, y = scaled(x), scaled(y)
        result += f"{x:+d}{y:+d}"
    return result


def force_square_corners(hwnd: int) -> tuple[bool, int | None]:
    """Ask Windows 11 DWM to never round one top-level HWND."""
    if os.name != "nt" or windows_build() < WINDOWS_11_BUILD or not hwnd:
        return False, None
    return set_dwm_int_attribute(hwnd, DWMWA_WINDOW_CORNER_PREFERENCE, DWMWCP_DONOTROUND)


def set_dark_title_bar(hwnd: int, enabled: bool) -> tuple[bool, int | None]:
    """Ask DWM to match the native title bar to WinDevPilot's dark/light palette."""
    if os.name != "nt" or not hwnd:
        return False, None
    return set_dwm_int_attribute(hwnd, DWMWA_USE_IMMERSIVE_DARK_MODE, 1 if enabled else 0)


@functools.lru_cache(maxsize=1)
def _dwm_set_window_attribute() -> Any | None:
    """Return one configured DWM setter instead of reopening the DLL per event."""

    if os.name != "nt":
        return None
    try:
        dwmapi = ctypes.WinDLL("dwmapi", use_last_error=True)
        setter = dwmapi.DwmSetWindowAttribute
        setter.argtypes = [
            ctypes.c_void_p,
            ctypes.c_uint,
            ctypes.c_void_p,
            ctypes.c_uint,
        ]
        setter.restype = ctypes.c_long
        return setter
    except (AttributeError, OSError):
        return None


def set_dwm_int_attribute(hwnd: int, attribute: int, value: int) -> tuple[bool, int | None]:
    """Set a single integer-valued DWM attribute on a Tk top-level HWND."""
    if os.name != "nt" or not hwnd:
        return False, None
    try:
        setter = _dwm_set_window_attribute()
        if setter is None:
            return False, None
        native_value = ctypes.c_int(value)
        top_level_hwnd = native_top_level_hwnd(hwnd)
        hresult = int(
            setter(
                ctypes.c_void_p(top_level_hwnd),
                attribute,
                ctypes.byref(native_value),
                ctypes.sizeof(native_value),
            )
        )
        return hresult == 0, hresult
    except (AttributeError, OSError):
        return False, None


def colorref_from_hex(color: str) -> int:
    """Convert #rrggbb to Windows COLORREF 0x00bbggrr."""
    red = int(color[1:3], 16)
    green = int(color[3:5], 16)
    blue = int(color[5:7], 16)
    return red | (green << 8) | (blue << 16)


def set_dwm_color_attribute(hwnd: int, attribute: int, color: str) -> tuple[bool, int | None]:
    if os.name != "nt" or windows_build() < WINDOWS_11_BUILD or not hwnd:
        return False, None
    try:
        return set_dwm_int_attribute(hwnd, attribute, colorref_from_hex(color))
    except ValueError:
        return False, None


def set_title_bar_palette(
    hwnd: int, *, dark: bool, active: bool, colors: dict[str, str]
) -> dict[str, Any]:
    """Apply best-effort DWM caption colors for active/inactive top-level windows."""
    dark_applied, dark_hresult = set_dark_title_bar(hwnd, dark)
    suffix = "active" if active else "inactive"
    caption_applied, caption_hresult = set_dwm_color_attribute(
        hwnd, DWMWA_CAPTION_COLOR, colors[f"chrome_{suffix}_caption"]
    )
    text_applied, text_hresult = set_dwm_color_attribute(
        hwnd, DWMWA_TEXT_COLOR, colors[f"chrome_{suffix}_text"]
    )
    border_applied, border_hresult = set_dwm_color_attribute(
        hwnd, DWMWA_BORDER_COLOR, colors[f"chrome_{suffix}_border"]
    )
    return {
        "dark_applied": dark_applied,
        "dark_hresult": dark_hresult,
        "caption_applied": caption_applied,
        "caption_hresult": caption_hresult,
        "text_applied": text_applied,
        "text_hresult": text_hresult,
        "border_applied": border_applied,
        "border_hresult": border_hresult,
    }


WINDOW_RESIZE_STATE_MESSAGES = frozenset(
    {
        0x001F,  # WM_CANCELMODE
        0x0005,  # WM_SIZE
        0x0214,  # WM_SIZING
        0x0215,  # WM_CAPTURECHANGED
        0x0231,  # WM_ENTERSIZEMOVE
        0x0232,  # WM_EXITSIZEMOVE
        0x02E0,  # WM_DPICHANGED
    }
)


@functools.lru_cache(maxsize=1)
def _resize_subclass_api() -> tuple[Any, Any]:
    """Keep one ABI-correct callback alive for the process; preserve Tk's subclass chain."""
    library = ctypes.WinDLL("comctl32", use_last_error=True)
    procedure_type = ctypes.WINFUNCTYPE(
        ctypes.c_ssize_t, ctypes.c_void_p, ctypes.c_uint, ctypes.c_size_t,
        ctypes.c_ssize_t, ctypes.c_size_t, ctypes.c_size_t,
    )
    library.SetWindowSubclass.argtypes = [
        ctypes.c_void_p, procedure_type, ctypes.c_size_t, ctypes.c_size_t,
    ]
    library.SetWindowSubclass.restype = ctypes.c_int
    library.RemoveWindowSubclass.argtypes = [ctypes.c_void_p, procedure_type, ctypes.c_size_t]
    library.RemoveWindowSubclass.restype = ctypes.c_int
    library.DefSubclassProc.argtypes = [
        ctypes.c_void_p, ctypes.c_uint, ctypes.c_size_t, ctypes.c_ssize_t,
    ]
    library.DefSubclassProc.restype = ctypes.c_ssize_t

    @procedure_type
    def procedure(hwnd: int, message: int, wparam: int, lparam: int,
                  identity: int, _reference: int) -> int:
        # Entering a Python ctypes callback still needs the GIL. Keep the very
        # frequent move/paint/mouse messages out of all additional Python work;
        # only the small state machine below needs controller dispatch.
        if message == 0x0082 or message in WINDOW_RESIZE_STATE_MESSAGES:
            controller = WindowsResizeHold._native_instances.get(identity)
        else:
            controller = None
        if controller is not None:
            try:
                if message == 0x0082:  # WM_NCDESTROY: Tk widgets may already be gone.
                    controller._set_interactive_thread_switching(False)
                    controller._closed = True
                    controller._layout.clear()
                    library.RemoveWindowSubclass(hwnd, procedure, identity)
                    WindowsResizeHold._native_instances.pop(identity, None)
                    controller._hwnd = 0
                else:
                    controller._on_message(message, wparam)
            except BaseException as exc:
                # A Python exception must never escape through the native ABI.
                controller._fail(exc)
        return int(library.DefSubclassProc(hwnd, message, wparam, lparam))

    return library, procedure


class WindowsResizeHold:
    """Hold two existing packed root children only during actual native sizing.

    The native callback records intent only: entering Tcl there can invalidate
    _tkinter's saved thread state. Layout runs in Tk callbacks, with a short
    release check only while held. Every native message continues through Tk.
    """

    _native_instances: ClassVar[dict[int, WindowsResizeHold]] = {}

    def __init__(self, root: Any, children: Sequence[Any],
                 report_error: Callable[[str], None] | None = None) -> None:
        self.root = root
        self.children = tuple(children)
        self.report_error = report_error
        self._layout: list[tuple[Any, dict[str, Any]]] = []
        self._in_loop = False
        self._suspended = False
        self._wants_hold = False
        self._closed = False
        self._disabled = False
        self._hwnd = 0
        self.error = ""
        self._after_id: str | None = None
        self._normal_thread_switch_interval = sys.getswitchinterval()
        self._interactive_thread_switching = False
        self._configure_binding = root.bind("<Configure>", self._on_configure, add="+")
        self._destroy_binding = root.bind("<Destroy>", self._on_destroy, add="+")

    def install(self) -> bool:
        if self._hwnd:
            return True
        if os.name != "nt" or self._closed or self._disabled:
            return False
        try:
            library, procedure = _resize_subclass_api()
            hwnd = native_top_level_hwnd(int(self.root.winfo_id()))
            if not library.SetWindowSubclass(hwnd, procedure, id(self), 0):
                raise OSError("Windows could not attach the resize observer")
            self._hwnd = hwnd
            self._native_instances[id(self)] = self
            return True
        except Exception as exc:
            self._fail(exc)
            return False

    def _hold(self) -> None:
        if self._layout or not self.root.winfo_ismapped() or self.root.state() != "normal":
            return
        if tuple(self.root.pack_slaves()) != self.children:
            raise RuntimeError("Resize hold requires the original packed root children")
        allocated = [
            (child, child.pack_info(), child.winfo_x(), child.winfo_y(),
             child.winfo_width(), child.winfo_height())
            for child in self.children
        ]
        for child, options, x, y, width, height in allocated:
            # Remember before touching a manager, so a partial failure is reversible.
            self._layout.append((child, options))
            child.pack_forget()
            child.place(x=x, y=y, width=width, height=height)

    def _restore(self) -> None:
        layout, self._layout = self._layout, []
        first_error: Exception | None = None
        for child, options in layout:
            try:
                if child.winfo_exists():
                    child.place_forget()
                    child.pack(**options)
            except Exception as exc:
                self._layout.append((child, options))
                first_error = first_error or exc
        if first_error is not None:
            raise first_error

    def suspend(self) -> None:
        """Tk-thread release for theme/DPI changes; never called by the native callback."""
        self._suspended = True
        self._wants_hold = False
        self._cancel_poll()
        self._restore()

    def _set_interactive_thread_switching(self, active: bool) -> None:
        """Bound background GIL residency during an exclusive native gesture."""

        if active:
            if self._interactive_thread_switching:
                return
            self._normal_thread_switch_interval = sys.getswitchinterval()
            target = min(
                self._normal_thread_switch_interval,
                WINDOW_DRAG_THREAD_SWITCH_INTERVAL_SECONDS,
            )
            sys.setswitchinterval(target)
            self._interactive_thread_switching = True
            return
        if not self._interactive_thread_switching:
            return
        sys.setswitchinterval(self._normal_thread_switch_interval)
        self._interactive_thread_switching = False

    def _on_message(self, message: int, wparam: int = 0) -> None:
        """Native boundary: Python state only, no Tk calls (including after/event_generate)."""
        if self._closed:
            return
        if message == 0x0231:  # WM_ENTERSIZEMOVE: moving alone does not hold.
            self._set_interactive_thread_switching(True)
            self._in_loop, self._suspended, self._wants_hold = True, False, False
        elif message == 0x0214:  # WM_SIZING
            if self._in_loop and not self._suspended and not self._disabled:
                self._wants_hold = True
        elif message == 0x0232:  # WM_EXITSIZEMOVE
            self._set_interactive_thread_switching(False)
            self._in_loop, self._suspended, self._wants_hold = False, True, False
        elif message in (0x0215, 0x001F) and (  # Lost capture or cancelled modal loop.
            self._in_loop or self._layout or self._wants_hold
        ):
            self._set_interactive_thread_switching(False)
            self._in_loop, self._suspended, self._wants_hold = False, True, False
        elif message == 0x0005 and wparam in (1, 2):  # Minimize/maximize.
            self._set_interactive_thread_switching(False)
            self._in_loop, self._suspended, self._wants_hold = False, True, False
        elif message == 0x02E0:  # WM_DPICHANGED: leave the DPI payload to Tk.
            self._suspended, self._wants_hold = True, False

    def _on_configure(self, event: Any) -> None:
        # A pure window move produces many root Configure events but has no
        # child geometry to hold or restore. Keep that hot path out of Tcl.
        if event.widget is self.root and (self._wants_hold or self._layout):
            self._service()

    def _on_destroy(self, event: Any) -> None:
        if event.widget is self.root:
            self.close()

    def _cancel_poll(self) -> None:
        if self._after_id is not None:
            self.root.after_cancel(self._after_id)
            self._after_id = None

    def _poll_release(self) -> None:
        self._after_id = None
        self._service()

    def _service(self) -> None:
        """Called only by Tk's own event dispatch, never from a ctypes callback."""
        if self._closed:
            return
        try:
            if self._wants_hold and not self._disabled:
                self._hold()
                if self._layout and self._after_id is None:
                    self._after_id = self.root.after(16, self._poll_release)
            else:
                self._cancel_poll()
                self._restore()
        except Exception as exc:
            self._fail(exc)
            with contextlib.suppress(Exception):
                self.suspend()

    def _fail(self, exc: BaseException) -> None:
        # This may run at the native boundary; leave restoration to Tk.
        self._disabled = True
        self._wants_hold = False
        if not self.error:
            self.error = f"{type(exc).__name__}: {exc}"
            if self.report_error is not None:
                with contextlib.suppress(Exception):
                    self.report_error(self.error)

    def close(self) -> None:
        if self._closed:
            return
        self._set_interactive_thread_switching(False)
        self._closed = True
        try:
            self.suspend()
        except Exception as exc:
            self._fail(exc)
        for sequence, binding in (("<Configure>", self._configure_binding),
                                  ("<Destroy>", self._destroy_binding)):
            with contextlib.suppress(Exception):
                self.root.unbind(sequence, binding)
        if self._hwnd:
            library, procedure = _resize_subclass_api()
            if library.RemoveWindowSubclass(self._hwnd, procedure, id(self)):
                self._native_instances.pop(id(self), None)
                self._hwnd = 0
            # On failure retain the inert controller until WM_NCDESTROY. The
            # shared cached callback remains alive even after a controller exits.


class WindowsVisualController:
    """Own native Windows DPI/corner policy for Tk top-level windows."""

    def __init__(self, root: Any, bootstrap: DpiBootstrapResult) -> None:
        self.root = root
        self.bootstrap = bootstrap
        self.current_dpi = BASE_DPI
        self.corner_applied = False
        self.corner_hresult: int | None = None
        self.dark_title_bars = False
        self.dark_title_applied = False
        self.dark_title_hresult: int | None = None
        self.chrome_colors: dict[str, str] = {}
        self.chrome_caption_applied = False
        self.chrome_caption_hresult: int | None = None
        self.chrome_text_applied = False
        self.chrome_text_hresult: int | None = None
        self.chrome_border_applied = False
        self.chrome_border_hresult: int | None = None
        self._registered_toplevels: set[str] = set()
        self._last_chrome_state: dict[str, tuple[Any, ...]] = {}
        self._sync_pending = False
        self._dpi_callback: Any = None

    def initialize(self, dpi_callback: Any = None) -> None:
        self._dpi_callback = dpi_callback
        self.root.update_idletasks()
        self._sync_dpi(force=True)
        self.register_toplevel(self.root)
        self.root.bind("<Configure>", self._on_configure, add="+")

    def set_dpi_callback(self, callback: Any) -> None:
        self._dpi_callback = callback

    def set_dark_title_bars(self, enabled: bool) -> None:
        self.dark_title_bars = enabled
        self.register_toplevel(self.root)

    def set_chrome_colors(self, colors: dict[str, str]) -> None:
        self.chrome_colors = dict(colors)
        self.register_toplevel(self.root)

    def px(self, value: int | float) -> int:
        return dip_to_px(value, self.current_dpi)

    def geometry_from_dips(self, geometry: str) -> str:
        return scale_geometry_spec(geometry, self.current_dpi / BASE_DPI, scale_position=True)

    def restore_geometry(self, geometry: str, stored_dpi: int) -> str:
        if stored_dpi > 0:
            return scale_geometry_spec(geometry, self.current_dpi / stored_dpi)
        return self.geometry_from_dips(geometry)

    def register_toplevel(self, window: Any) -> None:
        def apply(event: Any = None, *, active: bool | None = None) -> None:
            if event is not None and event.widget is not window:
                return
            try:
                if not window.winfo_exists():
                    return
            except Exception:
                # A queued after_idle callback can outlive its Toplevel.
                return
            self._apply_window_chrome(window, active=active)

        widget_name = str(window)
        if widget_name not in self._registered_toplevels:
            def refresh_focus(event: Any) -> None:
                try:
                    if str(event.widget.winfo_toplevel()) != str(window):
                        return
                    window.after_idle(apply)
                except Exception:
                    return

            def forget(event: Any) -> None:
                if event.widget is not window:
                    return
                self._registered_toplevels.discard(widget_name)
                self._last_chrome_state.pop(widget_name, None)

            self._registered_toplevels.add(widget_name)
            window.bind("<Map>", apply, add="+")
            window.bind("<FocusIn>", refresh_focus, add="+")
            window.bind("<FocusOut>", refresh_focus, add="+")
            window.bind("<Destroy>", forget, add="+")
        window.after_idle(apply)

    def _apply_window_chrome(self, window: Any, *, active: bool | None = None) -> None:
        try:
            if not window.winfo_exists():
                return
            hwnd = int(window.winfo_id())
        except Exception:
            # Tk may destroy a transient window before its idle chrome pass.
            return
        if active is None:
            focused = self.root.focus_get()
            active = focused is not None and str(focused.winfo_toplevel()) == str(window)
        widget_name = str(window)
        state = (
            hwnd,
            self.dark_title_bars,
            bool(active),
            tuple(sorted(self.chrome_colors.items())),
        )
        if self._last_chrome_state.get(widget_name) == state:
            return
        applied, hresult = force_square_corners(hwnd)
        if self.chrome_colors:
            chrome_result = set_title_bar_palette(
                hwnd,
                dark=self.dark_title_bars,
                active=active,
                colors=self.chrome_colors,
            )
            dark_applied = bool(chrome_result["dark_applied"])
            dark_hresult = chrome_result["dark_hresult"]
        else:
            chrome_result = {}
            dark_applied, dark_hresult = set_dark_title_bar(hwnd, self.dark_title_bars)
        self._last_chrome_state[widget_name] = state
        if window is self.root:
            self.corner_applied = applied
            self.corner_hresult = hresult
            self.dark_title_applied = dark_applied
            self.dark_title_hresult = dark_hresult
            self.chrome_caption_applied = bool(chrome_result.get("caption_applied", False))
            self.chrome_caption_hresult = chrome_result.get("caption_hresult")
            self.chrome_text_applied = bool(chrome_result.get("text_applied", False))
            self.chrome_text_hresult = chrome_result.get("text_hresult")
            self.chrome_border_applied = bool(chrome_result.get("border_applied", False))
            self.chrome_border_hresult = chrome_result.get("border_hresult")

    def prepare_first_show(self, window: Any | None = None) -> None:
        self._apply_window_chrome(self.root if window is None else window, active=True)

    def _on_configure(self, event: Any) -> None:
        if event.widget is not self.root or self._sync_pending:
            return
        self._sync_pending = True
        self.root.after(100, self._deferred_sync)

    def _deferred_sync(self) -> None:
        self._sync_pending = False
        self._sync_dpi()

    def _sync_dpi(self, *, force: bool = False) -> None:
        # initialize() already realizes startup geometry. Later DPI probes must
        # not recursively dispatch unrelated layout/paint callbacks.
        dpi = get_window_dpi(int(self.root.winfo_id()))
        if not force and dpi == self.current_dpi:
            return
        self.current_dpi = dpi
        tk_scaling = dpi / TK_POINTS_PER_INCH
        self.root.tk.call("tk", "scaling", "-displayof", self.root._w, tk_scaling)
        if self._dpi_callback is not None:
            self._dpi_callback(dpi)

    def diagnostics(self) -> dict[str, Any]:
        return {
            "windows_build": windows_build(),
            "dpi_bootstrap": self.bootstrap.to_dict(),
            "window_dpi": self.current_dpi,
            "scale_percent": round(self.current_dpi * 100 / BASE_DPI),
            "tk_patchlevel": str(self.root.tk.call("info", "patchlevel")),
            "tk_scaling": float(self.root.tk.call("tk", "scaling", "-displayof", self.root._w)),
            "tk_pixels_per_inch": float(self.root.winfo_fpixels("1i")),
            "square_corners_supported": windows_build() >= WINDOWS_11_BUILD,
            "square_corners_applied": self.corner_applied,
            "square_corner_hresult": self.corner_hresult,
            "dark_title_bars_requested": self.dark_title_bars,
            "dark_title_bars_applied": self.dark_title_applied,
            "dark_title_bar_attribute_accepted": self.dark_title_applied,
            "dark_title_bar_hresult": self.dark_title_hresult,
            "chrome_caption_applied": self.chrome_caption_applied,
            "chrome_caption_hresult": self.chrome_caption_hresult,
            "chrome_text_applied": self.chrome_text_applied,
            "chrome_text_hresult": self.chrome_text_hresult,
            "chrome_border_applied": self.chrome_border_applied,
            "chrome_border_hresult": self.chrome_border_hresult,
        }


def local_app_data_root() -> Path:
    base = os.environ.get("LOCALAPPDATA") or str(Path.home() / "AppData" / "Local")
    return Path(base)


def app_data_dir() -> Path:
    return local_app_data_root() / APP_NAME


def cached_self_command(*arguments: str) -> list[str]:
    """Run this source through importlib so ordinary helper launches reuse bytecode."""

    return [
        sys.executable,
        "-X",
        f"pycache_prefix={app_data_dir() / 'pycache'}",
        "-m",
        SCRIPT_PATH.stem,
        *arguments,
    ]


def migrate_legacy_app_data(base_dir: str | Path | None = None) -> bool:
    """Move the preceding development build's local state to the current app name."""
    base = Path(base_dir) if base_dir is not None else local_app_data_root()
    legacy = base / LEGACY_APP_DATA_NAME
    current = base / APP_NAME
    if current.exists() or not legacy.is_dir() or legacy.is_symlink():
        return False
    try:
        legacy.rename(current)
    except OSError:
        return False
    return True


def portable_inventory_path() -> Path:
    return app_data_dir() / PORTABLE_CACHE_FILENAME


def installed_inventory_cache_path() -> Path:
    return app_data_dir() / INSTALLED_INVENTORY_CACHE_FILENAME

# ==================== Portable discovery and evidence policy ====================

@dataclasses.dataclass(frozen=True, slots=True)
class PortableSignature:
    key: str
    display_name: str
    filename_patterns: tuple[re.Pattern[str], ...]
    metadata_names: tuple[str, ...]
    winget_id: str = ""
    homepage: str = ""


@dataclasses.dataclass(frozen=True, slots=True)
class PortablePafMetadata:
    app_root: str
    app_id: str
    name: str
    publisher: str
    version: str
    executable: str
    icon_source: str
    homepage: str


@dataclasses.dataclass(frozen=True, slots=True)
class PortableEvidence:
    confidence: str
    score: int
    reasons: tuple[str, ...]
    name: str
    publisher: str
    original_filename: str


def _portable_patterns(*patterns: str) -> tuple[re.Pattern[str], ...]:
    return tuple(re.compile(pattern, re.IGNORECASE) for pattern in patterns)


PORTABLE_SIGNATURES: tuple[PortableSignature, ...] = (
    PortableSignature(
        "cpu-z",
        "CPU-Z",
        _portable_patterns(r"cpuz(?:_x(?:32|64))?(?:_[0-9.]+)?\.exe"),
        ("cpu-z", "cpuz"),
        "CPUID.CPU-Z",
        "https://www.cpuid.com/softwares/cpu-z.html",
    ),
    PortableSignature(
        "notepad-plus-plus",
        "Notepad++",
        _portable_patterns(r"notepad\+\+\.exe"),
        ("notepad++", "notepad plus plus"),
        "Notepad++.Notepad++",
        "https://notepad-plus-plus.org/downloads/",
    ),
    PortableSignature(
        "rufus",
        "Rufus",
        _portable_patterns(r"rufus(?:-[0-9][0-9a-z._-]*)?(?:p)?\.exe"),
        ("rufus",),
        "Rufus.Rufus",
        "https://rufus.ie/",
    ),
    PortableSignature(
        "chathy",
        "Chathy",
        _portable_patterns(r"chathy\.exe"),
        ("chathy",),
    ),
)

PORTABLE_PRUNED_DIRECTORY_NAMES = frozenset(
    {
        "$recycle.bin",
        ".git",
        ".hg",
        ".idea",
        ".mypy_cache",
        ".nox",
        ".pytest_cache",
        ".ruff_cache",
        ".svn",
        ".tox",
        ".venv",
        ".vs",
        "__pycache__",
        "node_modules",
        "obj",
        "packages",
        "system volume information",
        "target",
        "venv",
        "windowsapps",
    }
)


@functools.lru_cache(maxsize=8192)
def _portable_path_key(path: str | Path) -> str:
    expanded = os.path.expandvars(os.path.expanduser(str(path)))
    normalized = os.path.normcase(os.path.abspath(expanded))
    drive, root, _tail = os.path.splitroot(normalized)
    anchor = drive + root
    return normalized if anchor and normalized == anchor else normalized.rstrip("\\/")


def _portable_path_is_within(path: str | Path, root: str | Path) -> bool:
    try:
        path_key = _portable_path_key(path)
        root_key = _portable_path_key(root)
        return os.path.commonpath((path_key, root_key)) == root_key
    except (OSError, ValueError):
        return False


@functools.lru_cache(maxsize=1)
def portable_system_install_roots() -> tuple[Path, ...]:
    """Return exact Windows-managed roots that portable discovery must not enter."""

    values = [
        os.environ.get("SystemRoot", ""),
        os.environ.get("WINDIR", ""),
        os.environ.get("ProgramFiles", ""),
        os.environ.get("ProgramFiles(x86)", ""),
        os.environ.get("ProgramW6432", ""),
    ]
    if system_drive := os.environ.get("SystemDrive", ""):
        values.extend(
            (
                str(Path(system_drive) / "Windows"),
                str(Path(system_drive) / "Program Files"),
                str(Path(system_drive) / "Program Files (x86)"),
            )
        )
    unique: dict[str, Path] = {}
    for value in values:
        if value:
            unique.setdefault(_portable_path_key(value), Path(value))
    return tuple(unique.values())


def portable_scan_root_rejection(root: str | Path) -> str:
    selected = Path(root).expanduser().absolute()
    if selected.exists() and _portable_path_is_reparse_point(selected):
        return (
            f"{selected} is a filesystem link or junction. Select the real portable-app "
            "folder so the scan cannot cross an unexpected directory boundary."
        )
    for protected in portable_system_install_roots():
        if _portable_path_is_within(selected, protected):
            return (
                f"{selected} is inside the Windows-managed {protected} tree. "
                "Portable scanning skips registered system/application folders."
            )
    return ""


def portable_scan_is_broad_root(root: str | Path) -> bool:
    """Return whether a selection covers an entire drive rather than an intentional app area."""

    selected = Path(root).expanduser().absolute()
    anchor = selected.anchor
    return bool(anchor) and _portable_path_key(selected) == _portable_path_key(anchor)


def _portable_path_parts(path: str | Path) -> tuple[str, ...]:
    return tuple(part.casefold() for part in Path(path).parts)


def _portable_parts_contain(parts: Sequence[str], sequence: Sequence[str]) -> bool:
    wanted = tuple(value.casefold() for value in sequence)
    return any(
        tuple(parts[index : index + len(wanted)]) == wanted
        for index in range(max(0, len(parts) - len(wanted) + 1))
    )


def portable_broad_directory_rejection(
    candidate: str | Path, scan_root: str | Path
) -> str:
    """Prune account-private and manager-owned trees during a whole-drive scan."""

    if not portable_scan_is_broad_root(scan_root):
        return ""
    path = Path(candidate)
    program_data = os.environ.get("PROGRAMDATA", "")
    if program_data and _portable_path_is_within(path, program_data):
        return "Windows ProgramData application/component tree"

    home = Path.home()
    users_root = home.parent
    if _portable_path_is_within(path, users_root):
        try:
            relative_parts = Path(_portable_path_key(path)).relative_to(
                Path(_portable_path_key(users_root))
            ).parts
        except ValueError:
            relative_parts = ()
        if relative_parts and relative_parts[0].casefold() != home.name.casefold():
            return "another Windows account profile"
        if _portable_path_is_within(path, home):
            try:
                home_parts = Path(_portable_path_key(path)).relative_to(
                    Path(_portable_path_key(home))
                ).parts
            except ValueError:
                home_parts = ()
            if home_parts and home_parts[0].casefold() in {
                "appdata",
                ".cache",
                ".codeium",
                ".lmstudio",
            }:
                return "current-account application/cache tree"

    if path.parent == Path(path.anchor) and path.name.casefold() in {
        "adobetemp",
    }:
        return "vendor staging tree"
    return ""


def _portable_path_uses_installed_convention(path: str | Path) -> bool:
    parts = _portable_path_parts(path)
    return _portable_parts_contain(parts, ("appdata", "local", "programs"))


def _portable_path_has_affirmative_container(
    executable: str | Path, scan_root: str | Path
) -> bool:
    root = Path(scan_root)
    root_key = _portable_path_key(root)
    current = Path(executable).parent
    while _portable_path_is_within(current, root):
        if current.name.casefold() in {
            "portable",
            "portables",
            "portableapps",
            "utilities",
        }:
            return True
        if _portable_path_key(current) == root_key or current.parent == current:
            break
        current = current.parent
    return False


def _portable_signature_filename_matches(
    signature: PortableSignature, executable: str | Path
) -> bool:
    return any(pattern.fullmatch(Path(executable).name) for pattern in signature.filename_patterns)


def executable_folder_on_path(executable: str | Path, env_path: str | None = None) -> bool:
    executable_folder = _portable_path_key(Path(executable).parent)
    path_value = os.environ.get("PATH", "") if env_path is None else env_path
    for raw_entry in path_value.split(os.pathsep):
        entry = os.path.expandvars(raw_entry.strip().strip('"'))
        if entry and _portable_path_key(entry) == executable_folder:
            return True
    return False


@functools.lru_cache(maxsize=1)
def _windows_version_api() -> Any | None:
    """Return one configured version-resource API handle for portable scans."""

    if os.name != "nt":
        return None
    try:
        version = ctypes.WinDLL("version", use_last_error=True)
        version.GetFileVersionInfoSizeW.argtypes = [
            ctypes.c_wchar_p,
            ctypes.POINTER(ctypes.c_uint32),
        ]
        version.GetFileVersionInfoSizeW.restype = ctypes.c_uint32
        version.GetFileVersionInfoW.argtypes = [
            ctypes.c_wchar_p,
            ctypes.c_uint32,
            ctypes.c_uint32,
            ctypes.c_void_p,
        ]
        version.GetFileVersionInfoW.restype = ctypes.c_int
        version.VerQueryValueW.argtypes = [
            ctypes.c_void_p,
            ctypes.c_wchar_p,
            ctypes.POINTER(ctypes.c_void_p),
            ctypes.POINTER(ctypes.c_uint),
        ]
        version.VerQueryValueW.restype = ctypes.c_int
        return version
    except (AttributeError, OSError):
        return None


def _extended_windows_path(path: str | Path) -> str:
    original = str(path)
    if original.startswith(("\\\\?\\", "\\\\.\\")):
        return original
    filename = os.path.abspath(original)
    if len(filename) < 260:
        return filename
    if filename.startswith("\\\\"):
        return "\\\\?\\UNC\\" + filename[2:]
    return "\\\\?\\" + filename


def sanitize_windows_version_resource_text(value: Any, max_chars: int = 1024) -> str:
    """Bound one untrusted PE version-resource field for display and matching."""

    text = str(value).split("\0", 1)[0]
    printable = "".join(character if character.isprintable() else " " for character in text)
    return re.sub(r"\s+", " ", printable).strip()[:max_chars]


def address_range_within_owned_buffer(
    buffer_start: int,
    buffer_size: int,
    address: int,
    byte_count: int,
) -> bool:
    """Prove that one native address range stays inside a caller-owned buffer."""

    if buffer_start <= 0 or buffer_size < 0 or address <= 0 or byte_count < 0:
        return False
    offset = address - buffer_start
    return 0 <= offset <= buffer_size and byte_count <= buffer_size - offset


def windows_file_version_strings(path: str | Path) -> dict[str, str]:
    """Read a PE version resource without launching the candidate executable."""

    if os.name != "nt":
        return {}
    try:
        version = _windows_version_api()
        if version is None:
            return {}
        filename = _extended_windows_path(path)
        ignored = ctypes.c_uint32()
        size = int(version.GetFileVersionInfoSizeW(filename, ctypes.byref(ignored)))
        if size <= 0 or size > 16 * 1024 * 1024:
            return {}
        buffer = ctypes.create_string_buffer(size)
        if not version.GetFileVersionInfoW(filename, 0, size, buffer):
            return {}
        buffer_start = ctypes.addressof(buffer)

        def returned_range_is_valid(address: int | None, byte_count: int) -> bool:
            return bool(
                address
                and address_range_within_owned_buffer(
                    buffer_start,
                    size,
                    int(address),
                    byte_count,
                )
            )

        result: dict[str, str] = {}
        pointer = ctypes.c_void_p()
        length = ctypes.c_uint()
        if (
            version.VerQueryValueW(
                buffer,
                "\\",
                ctypes.byref(pointer),
                ctypes.byref(length),
            )
            and pointer.value
            and length.value >= 52
            and returned_range_is_valid(pointer.value, 52)
        ):
            fixed = struct.unpack_from("<13I", ctypes.string_at(pointer.value, 52))
            if fixed[0] == 0xFEEF04BD:
                file_ms, file_ls = fixed[2], fixed[3]
                product_ms, product_ls = fixed[4], fixed[5]
                result["FixedFileVersion"] = (
                    f"{file_ms >> 16}.{file_ms & 0xFFFF}."
                    f"{file_ls >> 16}.{file_ls & 0xFFFF}"
                )
                result["FixedProductVersion"] = (
                    f"{product_ms >> 16}.{product_ms & 0xFFFF}."
                    f"{product_ls >> 16}.{product_ls & 0xFFFF}"
                )

        translations: list[tuple[int, int]] = []
        pointer = ctypes.c_void_p()
        length = ctypes.c_uint()
        if version.VerQueryValueW(
            buffer, r"\VarFileInfo\Translation", ctypes.byref(pointer), ctypes.byref(length)
        ) and pointer.value:
            translation_length = int(length.value)
            translation_bytes = (
                ctypes.string_at(pointer.value, translation_length)
                if 0 < translation_length <= 4096
                and translation_length % 4 == 0
                and returned_range_is_valid(pointer.value, translation_length)
                else b""
            )
            for offset in range(0, len(translation_bytes) - 3, 4):
                translations.append(struct.unpack_from("<HH", translation_bytes, offset))
        translations.extend(((0x0409, 0x04B0), (0x0409, 0x04E4)))

        for field in (
            "ProductName",
            "CompanyName",
            "FileDescription",
            "OriginalFilename",
            "ProductVersion",
            "FileVersion",
        ):
            for language, codepage in dict.fromkeys(translations):
                sub_block = f"\\StringFileInfo\\{language:04x}{codepage:04x}\\{field}"
                pointer = ctypes.c_void_p()
                length = ctypes.c_uint()
                if not version.VerQueryValueW(
                    buffer, sub_block, ctypes.byref(pointer), ctypes.byref(length)
                ) or not pointer.value:
                    continue
                declared_characters = int(length.value)
                if not 1 < declared_characters <= 4097:
                    continue
                requested_bytes = declared_characters * ctypes.sizeof(ctypes.c_wchar)
                if not returned_range_is_valid(pointer.value, requested_bytes):
                    continue
                value = sanitize_windows_version_resource_text(
                    ctypes.wstring_at(pointer.value, declared_characters - 1)
                )
                if value:
                    result[field] = value
                    break
        return result
    except (AttributeError, OSError, TypeError, ValueError):
        return {}


def portable_signature_for(
    executable: str | Path,
    metadata: Mapping[str, str] | None = None,
) -> PortableSignature | None:
    filename = Path(executable).name
    for signature in PORTABLE_SIGNATURES:
        if any(pattern.fullmatch(filename) for pattern in signature.filename_patterns):
            return signature
    if not metadata:
        return None
    identity = " ".join(
        str(metadata.get(field, "")) for field in ("ProductName", "FileDescription")
    ).casefold()
    return next(
        (
            signature
            for signature in PORTABLE_SIGNATURES
            if any(name.casefold() in identity for name in signature.metadata_names)
        ),
        None,
    )


def _portable_version(metadata: Mapping[str, str], filename: str) -> str:
    for field in (
        "FixedProductVersion",
        "FixedFileVersion",
        "ProductVersion",
        "FileVersion",
    ):
        value = str(metadata.get(field, "")).strip()
        if value and any(character.isdigit() for character in value):
            # Numeric fixed versions are stable for comparisons; discard
            # meaningless trailing zero components without erasing 0 itself.
            if field.startswith("Fixed"):
                parts = value.split(".")
                while len(parts) > 2 and parts[-1] == "0":
                    parts.pop()
                return ".".join(parts)
            return value.replace(", ", ".")
    match = _PORTABLE_FILENAME_VERSION_RE.search(filename)
    return match.group(1) if match else "Unknown"


def read_portableapps_metadata(appinfo_path: str | Path) -> PortablePafMetadata | None:
    """Read one high-confidence PortableApps.com Format identity without execution."""

    path = Path(appinfo_path)
    try:
        if (
            path.name.casefold() != "appinfo.ini"
            or path.parent.name.casefold() != "appinfo"
            or path.parent.parent.name.casefold() != "app"
            or path.stat().st_size > 2 * 1024 * 1024
        ):
            return None
        app_root = path.parent.parent.parent.resolve(strict=True)
        app_directory = (app_root / "App").resolve(strict=True)
        parser = configparser.ConfigParser(interpolation=None)
        with path.open("r", encoding="utf-8-sig", errors="replace") as stream:
            parser.read_file(stream)
        if (
            parser.get("Format", "Type", fallback="").casefold()
            != "portableapps.comformat"
        ):
            return None
        name = parser.get("Details", "Name", fallback="").strip()
        app_id = parser.get("Details", "AppID", fallback="").strip()
        start = parser.get("Control", "Start", fallback="").strip()
        if not name or not app_id or not start:
            return None
        executable = (app_directory / start.replace("\\", os.sep)).resolve(strict=True)
        if (
            not executable.is_file()
            or executable.suffix.casefold() != ".exe"
            or not _portable_path_is_within(executable, app_directory)
        ):
            return None
        icon_value = parser.get("Control", "ExtractIcon", fallback="").split(",", 1)[0].strip()
        icon_candidates = []
        if icon_value:
            icon_candidates.extend(
                (
                    app_root / icon_value.replace("\\", os.sep),
                    app_directory / icon_value.replace("\\", os.sep),
                )
            )
        icon_candidates.extend(
            (
                app_directory / "AppInfo" / "appicon.ico",
                app_directory / "AppInfo" / "appicon1.ico",
                executable,
            )
        )
        icon_source = next(
            (
                candidate.resolve(strict=True)
                for candidate in icon_candidates
                if candidate.is_file()
                and _portable_path_is_within(candidate.resolve(strict=True), app_root)
            ),
            executable,
        )
        return PortablePafMetadata(
            app_root=str(app_root),
            app_id=app_id,
            name=name,
            publisher=parser.get("Details", "Publisher", fallback="").strip(),
            version=(
                parser.get("Version", "DisplayVersion", fallback="").strip()
                or parser.get("Version", "PackageVersion", fallback="").strip()
                or "Unknown"
            ),
            executable=str(executable),
            icon_source=str(icon_source),
            homepage=parser.get("Details", "Homepage", fallback="").strip(),
        )
    except (configparser.Error, OSError, RuntimeError, ValueError):
        return None


def _portable_display_name(metadata: Mapping[str, str], executable: Path) -> str:
    name = (
        str(metadata.get("ProductName", "")).strip()
        or str(metadata.get("FileDescription", "")).strip()
        or executable.stem
    )
    if name.casefold().endswith(" application") and len(name) > len(" application"):
        name = name[: -len(" application")].rstrip()
    return name[:160]


def _portable_generic_app_key(
    name: str,
    publisher: str,
) -> str:
    identity = "\0".join(
        (
            normalized_package_name(name),
            normalized_package_name(publisher),
        )
    )
    return f"generic-{hashlib.sha256(identity.encode()).hexdigest()[:20]}"


@dataclasses.dataclass(frozen=True, slots=True)
class PortableInstalledRegistrationIndex:
    """One portable scan's registration paths; never persisted between scans."""

    exact_paths: frozenset[str]
    folder_roots: frozenset[str]

    @classmethod
    def from_inventory(
        cls, inventory: WindowsInstalledInventory
    ) -> PortableInstalledRegistrationIndex:
        exact_paths: set[str] = set()
        folder_roots: set[str] = set()
        profile = Path.home()
        profile_parent = _portable_path_key(profile.parent)
        shared_roots = {
            _portable_path_key(path)
            for path in (*portable_system_install_roots(), profile, profile.parent)
        }
        shared_roots.update(
            _portable_path_key(value)
            for name in ("PUBLIC", "ProgramData", "APPDATA", "LOCALAPPDATA", "TEMP", "TMP")
            if (value := os.environ.get(name, ""))
        )
        shared_names = PORTABLE_SHARED_FOLDER_NAMES | {"portableapps"}

        def add_app_folder(value: str | Path) -> None:
            path = Path(os.path.expandvars(os.path.expanduser(str(value))))
            if not path.is_absolute():
                return
            key = _portable_path_key(path)
            parent = os.path.dirname(key)
            if (
                parent == key or key in shared_roots or parent == profile_parent
                or normalized_package_name(Path(key).name) in shared_names
            ):
                return
            folder_roots.add(key)

        for entry in inventory.entries:
            if entry.install_location:
                add_app_folder(entry.install_location)
            display_icon = strip_display_icon_index(entry.display_icon)
            if display_icon:
                # An icon identifies only that file, not its unrelated siblings.
                exact_paths.add(_portable_path_key(display_icon))
            uninstaller = local_executable_from_command(entry.uninstall_command)
            if uninstaller:
                exact_paths.add(_portable_path_key(uninstaller))
                add_app_folder(Path(uninstaller).parent)
        return cls(frozenset(exact_paths), frozenset(folder_roots))

    def contains(self, executable: str | Path) -> bool:
        current = _portable_path_key(executable)
        if current in self.exact_paths:
            return True
        # Lexical ancestors preserve commonpath's component boundaries, drive
        # roots and UNC shares without resolving or touching candidate files.
        while True:
            if current in self.folder_roots:
                return True
            parent = os.path.dirname(current)
            if parent == current:
                return False
            current = parent


def _portable_path_has_installed_registration(
    executable: Path,
    installed_inventory: WindowsInstalledInventory | PortableInstalledRegistrationIndex,
) -> bool:
    index = (
        installed_inventory
        if isinstance(installed_inventory, PortableInstalledRegistrationIndex)
        else PortableInstalledRegistrationIndex.from_inventory(installed_inventory)
    )
    return index.contains(executable)


def _portable_installer_identity_rejection(
    executable: str | Path,
    original_filename: str,
) -> str:
    """Reject strong installer/helper evidence that is safe to apply to cached rows."""

    hard_identity_text = (
        f"{Path(executable).name} "
        f"{sanitize_windows_version_resource_text(original_filename, 260)}"
    ).casefold()
    if _PORTABLE_INSTALLER_IDENTITY_RE.search(hard_identity_text):
        return "looks like an installer, remover, updater, redistributable, or helper"
    return ""


def portable_candidate_rejection(
    executable: str | Path,
    metadata: Mapping[str, str],
    installed_inventory: WindowsInstalledInventory | PortableInstalledRegistrationIndex,
    *,
    broad_scan: bool,
) -> str:
    """Return a strong reason why a PE is not an independently managed portable app."""

    path = Path(executable)
    name = _portable_display_name(metadata, path)
    original = sanitize_windows_version_resource_text(
        metadata.get("OriginalFilename", ""), 260
    )
    identity_text = " ".join(
        (path.name, name, str(metadata.get("FileDescription", "")), original)
    ).casefold()
    path_text = str(path).casefold()
    if rejection := _portable_installer_identity_rejection(path, original):
        return rejection
    if _PORTABLE_CONTENT_TREE_RE.search(path_text):
        return "is inside an installed-app or game-content tree"
    if _portable_path_uses_installed_convention(path):
        return "is inside the conventional per-user installed-program tree"
    if _portable_path_has_installed_registration(path, installed_inventory):
        return "matches Windows uninstall registration"
    if any(
        _portable_path_is_within(path, root) for root in portable_system_install_roots()
    ):
        return "is inside a Windows installed-program location"
    if broad_scan:
        parts = _portable_path_parts(path)
        if any(
            part in {
                ".chromium-browser-snapshots",
                "depots",
                "drivers",
                "globalstorage",
                "ms-playwright",
                "ota-artifacts",
                "post-processing",
                "servicehub",
                "testtool",
            }
            for part in parts
        ):
            return "is inside a managed runtime, driver, test, or application-component tree"
        if _PORTABLE_COMPONENT_IDENTITY_RE.search(identity_text):
            return "looks like an application component, plugin, or registration helper"
    return ""


def _portable_folder_identity_match(
    folder: Path,
    executable: Path,
    name: str,
    original: str,
) -> bool:
    """Return whether a non-shared folder is credibly owned by one portable app."""

    folder_identity = _portable_identity_text(folder.name)
    if (
        not folder_identity
        or len(folder_identity) < 4
        or folder_identity in PORTABLE_SHARED_FOLDER_NAMES
    ):
        return False
    aliases = {
        _portable_identity_text(name),
        _portable_identity_text(executable.stem),
        _portable_identity_text(Path(original).stem),
    }
    return any(
        len(alias) >= 4
        and (
            alias == folder_identity
            or alias in folder_identity
            or folder_identity in alias
        )
        for alias in aliases
    )


def _portable_generic_folder_match(executable: Path, name: str, original: str) -> bool:
    return _portable_folder_identity_match(
        executable.parent,
        executable,
        name,
        original,
    )


def portable_pe_subsystem(executable: str | Path) -> int | None:
    """Read IMAGE_OPTIONAL_HEADER.Subsystem without loading or executing the PE."""

    path = Path(executable)
    try:
        size = path.stat().st_size
        if size < 96:
            return None
        with path.open("rb") as stream:
            if stream.read(2) != b"MZ":
                return None
            stream.seek(0x3C)
            offset_bytes = stream.read(4)
            if len(offset_bytes) != 4:
                return None
            pe_offset = struct.unpack("<I", offset_bytes)[0]
            if pe_offset > size - 96:
                return None
            stream.seek(pe_offset)
            if stream.read(4) != b"PE\0\0":
                return None
            coff = stream.read(20)
            if len(coff) != 20:
                return None
            optional_size = struct.unpack_from("<H", coff, 16)[0]
            if optional_size < 70:
                return None
            optional = stream.read(min(optional_size, 70))
            if len(optional) < 70 or struct.unpack_from("<H", optional)[0] not in {
                0x10B,
                0x20B,
            }:
                return None
            return struct.unpack_from("<H", optional, 68)[0]
    except (OSError, ValueError, struct.error):
        return None


def _portable_local_state_marker(executable: Path, name: str) -> str:
    """Return one strong app-local portability marker, avoiding generic JSON/XML."""

    identities = {
        normalized_package_name(executable.stem),
        normalized_package_name(name),
    }
    try:
        for candidate in executable.parent.iterdir():
            if not candidate.is_file():
                continue
            folded = candidate.name.casefold()
            if folded in {
                ".portable",
                "portable",
                "portable.dat",
                "portable.ini",
                "portableapps.com",
            }:
                return candidate.name
            if candidate.suffix.casefold() == ".ini" and normalized_package_name(
                candidate.stem
            ) in identities:
                return candidate.name
    except OSError:
        pass
    return ""


def portable_generic_evidence(
    executable: str | Path,
    metadata: Mapping[str, str],
    installed_inventory: WindowsInstalledInventory | PortableInstalledRegistrationIndex,
    *,
    scan_root: str | Path,
    broad_scan: bool,
) -> PortableEvidence:
    """Classify generic PE candidates conservatively; only ``high`` is displayed."""

    path = Path(executable)
    name = _portable_display_name(metadata, path)
    publisher = str(metadata.get("CompanyName", "")).strip()[:160]
    original = str(metadata.get("OriginalFilename", "")).strip()[:260]
    if rejection := portable_candidate_rejection(
        path,
        metadata,
        installed_inventory,
        broad_scan=broad_scan,
    ):
        return PortableEvidence("rejected", -100, (rejection,), name, publisher, original)
    generic_names = {
        "",
        "application",
        "program",
        "sfx",
        "uninstaller",
        "upgradetool",
    }
    normalized_name = normalized_package_name(name)
    if normalized_name in generic_names or not (
        metadata.get("ProductName") or metadata.get("FileDescription")
    ):
        return PortableEvidence(
            "unlikely",
            0,
            ("no meaningful PE product identity",),
            name,
            publisher,
            original,
        )

    score = 35
    reasons = ["meaningful PE product identity"]
    reasons.append("outside Windows installed-program locations")
    descriptive_text = " ".join(
        (
            name,
            str(metadata.get("FileDescription", "")),
        )
    )
    if _PORTABLE_HELPER_DESCRIPTION_RE.search(descriptive_text):
        score -= 30
        reasons.append(
            "product description resembles packaging/helper software; stronger "
            "portable evidence is required"
        )
    if publisher:
        score += 10
        reasons.append("PE metadata includes a stable publisher identity")
    stem_identity = _portable_identity_text(path.stem)
    product_identity = _portable_identity_text(name)
    original_identity = _portable_identity_text(Path(original).stem)
    product_identity_match = any(
        len(identity) >= 4
        and (
            identity in stem_identity
            or stem_identity in identity
        )
        for identity in (product_identity,)
    )
    original_identity_match = bool(
        len(original_identity) >= 4
        and (
            original_identity in stem_identity
            or stem_identity in original_identity
        )
    )
    if original_identity_match:
        score += 15
        reasons.append("filename agrees with the embedded original filename")
    elif product_identity_match:
        # ProductName commonly describes both an application's executable and
        # its single-file installer. It is useful corroboration, but on a whole
        # drive it must not combine with PATH/container placement alone to make
        # an installer-looking payload user-visible.
        score += 5 if broad_scan else 15
        reasons.append("filename agrees with PE product identity")
    folder_identity_match = _portable_generic_folder_match(path, name, original)
    if folder_identity_match:
        score += 25
        reasons.append("app-owned folder name agrees with executable identity")
        if _portable_path_key(path.parent) == _portable_path_key(scan_root):
            score += 10
            reasons.append(
                "the exact folder selected by the user agrees with executable identity"
            )
    if "portable" in path.name.casefold() or "portable" in path.parent.name.casefold():
        score += 30
        reasons.append("filename or containing folder explicitly says portable")
    if marker := _portable_local_state_marker(path, name):
        score += 30
        reasons.append(f"app-local portability marker: {marker}")
    family_text = f"{publisher} {name} {path.parent.name}".casefold()
    if "nirsoft" in family_text or "sysinternals" in family_text:
        score += 30
        reasons.append("recognized portable-first publisher family")
    reasons.append("no matching Windows uninstall registration")
    if executable_folder_on_path(path):
        score += 25
        reasons.append("executable folder is on the current account PATH")
    if _portable_path_has_affirmative_container(path, scan_root):
        score += 25
        reasons.append("stored beneath an explicit portable/utilities container")
    if not broad_scan:
        score += 20
        reasons.append("inside the bounded folder explicitly selected by the user")
    subsystem = portable_pe_subsystem(path)
    if subsystem == 2:
        reasons.append("PE subsystem: Windows GUI")
    elif subsystem == 3:
        reasons.append("PE subsystem: console")
    # A matching filename and folder alone can also describe an unpacked build
    # artifact. Require one more independent signal (normally a publisher,
    # explicit portable naming, or a portable-first vendor family) before a
    # generic executable becomes user-visible.
    confidence = "high" if score >= 105 else "review" if score >= 65 else "unlikely"
    return PortableEvidence(confidence, score, tuple(reasons), name, publisher, original)


def _portable_representative_rank(
    record: PortableRecord,
) -> tuple[int, int, int, int, int, int]:
    """Prefer the primary GUI/x64 executable among same-app folder siblings."""

    stem = Path(record.executable).stem.casefold()
    auxiliary = bool(_PORTABLE_AUXILIARY_STEM_RE.search(stem))
    return (
        record.evidence_score,
        int(portable_pe_subsystem(record.executable) == 2),
        int(not auxiliary),
        int("x64" in stem or "64" in stem),
        int(_portable_path_key(record.icon_source) != _portable_path_key(record.executable)),
        -len(Path(record.executable).name),
    )


def choose_portable_icon_source(
    executable: str | Path,
    signature: PortableSignature | None = None,
    *,
    display_name: str = "",
    preferred_icon: str | Path = "",
) -> Path:
    """Choose local artwork cheaply; image decoding stays in the lazy icon worker."""

    executable_path = Path(executable)
    preferred_path = Path(preferred_icon) if preferred_icon else None
    if preferred_path is not None and preferred_path.is_file():
        return preferred_path
    stem = executable_path.stem.casefold()
    search_directories = [executable_path.parent]
    with contextlib.suppress(OSError):
        with os.scandir(executable_path.parent) as entries:
            search_directories.extend(
                Path(entry.path)
                for entry in entries
                if entry.is_dir()
                and entry.name.casefold() in {"assets", "icons", "images", "resources"}
            )
    candidates: list[tuple[int, int, str, Path]] = []
    seen = 0
    identity_words = tuple(
        word
        for word in re.findall(
            r"[a-z0-9]+",
            (
                f"{signature.key} {signature.display_name}"
                if signature is not None
                else display_name
            ).casefold(),
        )
        if len(word) >= 3
    )
    for directory in search_directories:
        try:
            # DirEntry retains enumeration metadata on Windows. Keep the same
            # link-following behavior and full-filename tie-break as Path used.
            with os.scandir(directory) as entries:
                for entry in entries:
                    seen += 1
                    if seen > 1200:
                        break
                    if not entry.is_file():
                        continue
                    child = Path(entry.path)
                    suffix = child.suffix.casefold()
                    if suffix not in {".ico", ".png", ".dll", ".exe"}:
                        continue
                    child_stem = child.stem.casefold()
                    if child == executable_path:
                        score = 30
                    elif suffix in {".ico", ".png"} and child_stem == stem:
                        score = 0
                    elif suffix in {".ico", ".png"} and child_stem in {"app", "icon", "logo"}:
                        score = 5
                    elif suffix in {".ico", ".png"} and any(
                        word in child_stem for word in identity_words
                    ):
                        score = 10
                    elif suffix == ".dll" and child_stem == stem:
                        score = 20
                    else:
                        score = 70 if suffix in {".ico", ".png"} else 100
                    with contextlib.suppress(OSError):
                        candidates.append(
                            (score, -int(entry.stat().st_size), entry.name.casefold(), child)
                        )
            if seen > 1200:
                break
        except OSError:
            continue
    return min(candidates, default=(999, 0, "", executable_path))[3]


@dataclasses.dataclass(frozen=True, slots=True)
class PortableRemovalPlan:
    kind: str
    target: str
    reason: str
    inspected_entries: int


def _portable_signature_by_key(app_key: str) -> PortableSignature | None:
    return next(
        (signature for signature in PORTABLE_SIGNATURES if signature.key == app_key),
        None,
    )


def _portable_identity_text(value: str) -> str:
    return "".join(filter(str.isalnum, value.casefold()))


def _portable_folder_matches_app(
    folder: Path, executable: Path, signature: PortableSignature
) -> bool:
    folder_identity = _portable_identity_text(folder.name)
    if (
        not folder_identity
        or folder_identity in PORTABLE_SHARED_FOLDER_NAMES
        or len(folder_identity) < 4
    ):
        return False
    aliases = {
        _portable_identity_text(signature.key),
        _portable_identity_text(signature.display_name),
        _portable_identity_text(executable.stem),
    }
    return any(
        len(alias) >= 4
        and (
            alias == folder_identity
            or alias in folder_identity
            or folder_identity in alias
        )
        for alias in aliases
    )


def _portable_path_is_reparse_point(path: Path) -> bool:
    try:
        if path.is_symlink() or bool(getattr(path, "is_junction", lambda: False)()):
            return True
        attributes = int(getattr(path.lstat(), "st_file_attributes", 0))
        return bool(attributes & 0x400)
    except OSError:
        return True


def _portable_owned_folder_is_unambiguous(
    folder: Path,
    executable: Path,
    signature: PortableSignature,
) -> tuple[bool, int, str]:
    """Boundedly prove that a matching folder does not look shared with another app."""

    inspected = 0
    errors: list[str] = []
    if _portable_path_is_reparse_point(folder):
        return False, inspected, "the application folder is a reparse point or cannot be inspected"
    try:
        executable_resolved = executable.resolve(strict=True)
    except OSError:
        return False, inspected, "the application executable could not be resolved safely"
    app_aliases = {
        _portable_identity_text(signature.key),
        _portable_identity_text(signature.display_name),
        _portable_identity_text(executable.stem),
    }

    def on_error(error: OSError) -> None:
        errors.append(f"{type(error).__name__}: {error}")

    for current, directories, files in os.walk(folder, topdown=True, onerror=on_error):
        current_path = Path(current)
        if current_path != folder and _portable_path_is_reparse_point(current_path):
            return False, inspected, "a nested folder is a reparse point"
        for directory in directories:
            inspected += 1
            if inspected > PORTABLE_REMOVAL_MAX_ENTRIES:
                return False, inspected, "the folder footprint exceeded the removal review limit"
            candidate = current_path / directory
            if directory.casefold() in PORTABLE_AMBIGUOUS_FOLDER_MARKERS:
                return False, inspected, f"the folder contains shared/project marker {directory}"
            if _portable_path_is_reparse_point(candidate):
                return False, inspected, f"{directory} is a reparse point"
        for filename in files:
            inspected += 1
            if inspected > PORTABLE_REMOVAL_MAX_ENTRIES:
                return False, inspected, "the folder footprint exceeded the removal review limit"
            candidate = current_path / filename
            if _portable_path_is_reparse_point(candidate):
                return False, inspected, f"{filename} is a reparse point"
            if candidate.suffix.casefold() != ".exe":
                continue
            try:
                candidate_resolved = candidate.resolve(strict=True)
            except OSError:
                return False, inspected, f"{filename} could not be resolved safely"
            if candidate_resolved == executable_resolved:
                continue
            other_signature = portable_signature_for(candidate)
            if other_signature is not None:
                if other_signature.key != signature.key:
                    return (
                        False,
                        inspected,
                        f"another recognized app executable is present: {filename}",
                    )
                continue
            stem = _portable_identity_text(candidate.stem)
            if any(
                stem == helper or stem.startswith(helper)
                for helper in PORTABLE_HELPER_EXECUTABLE_STEMS
            ):
                continue
            if any(len(alias) >= 4 and alias in stem for alias in app_aliases):
                continue
            return False, inspected, f"an unrelated executable may be present: {filename}"
    if errors:
        return False, inspected, "part of the folder could not be inspected"
    return True, inspected, ""


def portable_removal_plan(
    *,
    app_key: str,
    executable: str | Path,
    scan_root: str | Path,
) -> PortableRemovalPlan | None:
    """Return a narrowly proven file/folder deletion plan, never a guessed uninstall."""

    signature = _portable_signature_by_key(app_key)
    if signature is None:
        return None
    try:
        executable_path = Path(executable).expanduser()
        root_path = Path(scan_root).expanduser()
        if (
            not executable_path.is_absolute()
            or not root_path.is_absolute()
            or not executable_path.is_file()
            or _portable_path_is_reparse_point(root_path)
            or _portable_path_is_reparse_point(executable_path)
        ):
            return None
        executable_resolved = executable_path.resolve(strict=True)
        root_resolved = root_path.resolve(strict=True)
        if not _portable_path_is_within(executable_resolved, root_resolved):
            return None
        folder = executable_resolved.parent
        folder_matches = _portable_folder_matches_app(folder, executable_resolved, signature)
        if folder_matches:
            if (
                folder.parent == folder
                or folder == Path.home().resolve(strict=False)
                or _portable_path_is_reparse_point(folder)
            ):
                return None
            safe, inspected, reason = _portable_owned_folder_is_unambiguous(
                folder,
                executable_resolved,
                signature,
            )
            if safe:
                return PortableRemovalPlan(
                    kind="folder",
                    target=str(folder),
                    reason=(
                        f"{folder.name} matches {signature.display_name} and its bounded "
                        "contents do not look shared with another application"
                    ),
                    inspected_entries=inspected,
                )
            # An app-named folder with ambiguous contents is not a loose-file install.
            return None
        if signature.key not in PORTABLE_STANDALONE_FILE_KEYS:
            return None
        return PortableRemovalPlan(
            kind="file",
            target=str(executable_resolved),
            reason=(
                f"{signature.display_name} is a recognized standalone executable in "
                "a shared or generically named folder; only that exact file will be removed"
            ),
            inspected_entries=1,
        )
    except (OSError, RuntimeError, ValueError):
        return None


@functools.cache
def windows_current_install_date() -> str:
    """Return Windows' own current-install date as a comparison clue only."""

    if os.name != "nt":
        return ""
    import winreg

    try:
        with winreg.OpenKey(
            winreg.HKEY_LOCAL_MACHINE,
            r"SOFTWARE\Microsoft\Windows NT\CurrentVersion",
        ) as key:
            raw, _value_type = winreg.QueryValueEx(key, "InstallDate")
        observed = dt.datetime.fromtimestamp(int(raw)).date()
    except (OSError, OverflowError, TypeError, ValueError):
        return ""
    if dt.date(2000, 1, 1) <= observed <= dt.date.today() + dt.timedelta(days=1):
        return observed.isoformat()
    return ""


def portable_executable_service_date(
    executable: str | Path,
    *,
    app_name: str = "",
    original_filename: str = "",
    scan_root: str | Path = "",
) -> tuple[str, str, str, tuple[str, ...]]:
    """Return the best explicitly approximate date available from one executable.

    Portable software normally has no installation ledger. On Windows, the
    executable's creation time is a useful copy/deployment clue while its
    last-write time may reflect either the build or a later replacement. An
    identity-matching app folder is stronger local-placement evidence. A
    bounded, non-recursive sample of nearby payload files can corroborate that
    folder or executable within one day. Old file dates remain useful as
    artifact provenance, but are explicitly identified as such when they
    predate the current Windows installation.
    """

    path = Path(executable)
    try:
        stat = path.stat()
    except OSError:
        return "", "", "", ()
    candidates: list[tuple[float, dt.date, str, Path]] = []

    def add_candidate(timestamp: Any, kind: str, evidence_path: Path) -> None:
        if not isinstance(timestamp, (int, float)) or not math.isfinite(timestamp):
            return
        try:
            observed = dt.datetime.fromtimestamp(timestamp).date()
        except (OSError, OverflowError, ValueError):
            return
        if dt.date(1980, 1, 1) <= observed <= dt.date.today() + dt.timedelta(days=1):
            candidates.append((float(timestamp), observed, kind, evidence_path))

    creation_time = getattr(stat, "st_birthtime", None)
    if creation_time is None and os.name == "nt":
        creation_time = stat.st_ctime
    add_candidate(creation_time, "executable-creation", path)
    add_candidate(stat.st_mtime, "executable-last-write", path)

    # A vendor/build timestamp is frequently preserved when an archive is
    # unpacked or a folder is migrated. Search only a few ancestors, stop at
    # the user-selected root, and accept a directory timestamp solely when the
    # folder name matches the app identity and is not a shared name such as
    # Utilities or Tools. This fixes preserved-old-binary cases without
    # assigning one shared folder's date to every loose executable inside it.
    try:
        root_key = _portable_path_key(scan_root) if scan_root else ""
        matching_folder: Path | None = None
        for depth, folder in enumerate(path.parents):
            if depth >= 4:
                break
            reached_scan_root = bool(
                root_key and _portable_path_key(folder) == root_key
            )
            if _portable_path_is_reparse_point(folder):
                if reached_scan_root:
                    break
                continue
            if _portable_folder_identity_match(
                folder,
                path,
                app_name,
                original_filename,
            ):
                matching_folder = folder
                folder_stat = folder.stat()
                folder_creation = getattr(folder_stat, "st_birthtime", None)
                if folder_creation is None and os.name == "nt":
                    folder_creation = folder_stat.st_ctime
                add_candidate(folder_creation, "app-folder-creation", folder)
                break
            if reached_scan_root:
                break
        if matching_folder is not None and not _portable_path_is_reparse_point(
            matching_folder
        ):
            inspected = 0
            accepted = 0
            with os.scandir(matching_folder) as entries:
                for entry in entries:
                    inspected += 1
                    if inspected > PORTABLE_DATE_SLEUTH_MAX_DIRECTORY_ENTRIES:
                        break
                    if accepted >= PORTABLE_DATE_SLEUTH_MAX_SIBLINGS:
                        break
                    try:
                        if (
                            entry.name.casefold() == path.name.casefold()
                            or not entry.is_file(follow_symlinks=False)
                            or Path(entry.name).suffix.casefold()
                            not in PORTABLE_DATE_SLEUTH_PAYLOAD_SUFFIXES
                        ):
                            continue
                        sibling_stat = entry.stat(follow_symlinks=False)
                    except OSError:
                        continue
                    sibling_creation = getattr(sibling_stat, "st_birthtime", None)
                    if sibling_creation is None and os.name == "nt":
                        sibling_creation = sibling_stat.st_ctime
                    before = len(candidates)
                    add_candidate(
                        sibling_creation,
                        "nearby-file-creation",
                        Path(entry.path),
                    )
                    accepted += int(len(candidates) > before)
    except (OSError, OverflowError, ValueError):
        pass
    if not candidates:
        return "", "", "", ()

    placement_candidates = [
        record for record in candidates if record[2] != "executable-last-write"
    ]
    best_cluster: list[tuple[float, dt.date, str, Path]] = []
    best_score: tuple[int, int, int, int, float] | None = None
    ordered_candidates = sorted(placement_candidates, key=lambda record: record[1])
    for start, left_record in enumerate(ordered_candidates):
        cluster: list[tuple[float, dt.date, str, Path]] = []
        for record in ordered_candidates[start:]:
            if (record[1] - left_record[1]).days > 1:
                break
            cluster.append(record)
        kinds = {record[2] for record in cluster}
        corroborated = (
            len({os.path.normcase(str(record[3])) for record in cluster}) >= 2
            and (
                (
                    "nearby-file-creation" in kinds
                    and bool(kinds & {"app-folder-creation", "executable-creation"})
                )
                or {"app-folder-creation", "executable-creation"} <= kinds
            )
        )
        if not corroborated:
            continue
        score = (
            len(kinds),
            min(len(cluster), PORTABLE_DATE_SLEUTH_MAX_SIBLINGS + 2),
            int("app-folder-creation" in kinds),
            int("executable-creation" in kinds),
            max(record[0] for record in cluster),
        )
        if best_score is None or score > best_score:
            best_score = score
            best_cluster = cluster

    if best_cluster:
        timestamp, observed_date, _kind, _evidence_path = max(
            best_cluster, key=lambda record: record[0]
        )
        observed = observed_date.isoformat()
        ordered_evidence = sorted(
            best_cluster,
            key=lambda record: (
                0
                if record[2] == "app-folder-creation"
                else 1
                if record[2] == "executable-creation"
                else 2,
                str(record[3]).casefold(),
            ),
        )
        evidence_paths = tuple(
            dict.fromkeys(str(record[3]) for record in ordered_evidence)
        )[:6]
        kinds = {record[2] for record in best_cluster}
        evidence_parts = []
        if "app-folder-creation" in kinds:
            evidence_parts.append("app-folder")
        if "executable-creation" in kinds:
            evidence_parts.append("executable")
        if "nearby-file-creation" in kinds:
            evidence_parts.append("nearby-file")
        evidence_label = "portable " + ", ".join(evidence_parts) + " creation times"
        source = (
            f"Corroborated {evidence_label} "
            f"({len(evidence_paths)} local objects agreed within one day; "
            "approximate placement or last-servicing clue)"
        )
        kind = "corroborated-local-placement"
    else:
        fallback_candidates = [
            record for record in candidates if record[2] != "nearby-file-creation"
        ]
        if not fallback_candidates:
            return "", "", "", ()
        timestamp, observed_date, kind, evidence_path = max(
            fallback_candidates,
            key=lambda record: (
                record[0],
                {"app-folder-creation": 2, "executable-creation": 1}.get(record[2], 0),
            ),
        )
        observed = observed_date.isoformat()
        evidence_paths = (str(evidence_path),)

    if kind == "app-folder-creation":
        source = (
            "Portable app folder creation time "
            "(approximate local-placement clue; newer than the preserved executable)"
        )
    elif kind == "executable-creation":
        source = (
            "Portable executable filesystem creation time "
            "(approximate; may reflect when it was copied here)"
        )
    elif kind == "executable-last-write":
        source = (
            "Portable executable last-write time "
            "(approximate; may reflect its build or replacement date)"
        )
    windows_date = windows_current_install_date()
    try:
        predates_windows = bool(
            windows_date
            and dt.date.fromisoformat(observed) < dt.date.fromisoformat(windows_date)
        )
    except ValueError:
        predates_windows = False
    if predates_windows:
        source += (
            f"; predates Windows' recorded {windows_date} installation, so this is "
            "evidence from an earlier local placement or file vintage"
        )
    return observed, epoch_storage_timestamp(timestamp), source, evidence_paths


@dataclasses.dataclass(frozen=True, slots=True)
class PortableRecord:
    app_key: str
    name: str
    version: str
    executable: str
    icon_source: str
    scan_root: str
    detected_by: str
    path_on_path: bool
    publisher: str = ""
    original_filename: str = ""
    homepage: str = ""
    detection_confidence: str = "known"
    evidence_score: int = 100
    evidence_reasons: tuple[str, ...] = ()
    portable_format: str = ""
    catalog_package_id: str = ""
    catalog_name: str = ""
    catalog_available_version: str = ""
    catalog_homepage: str = ""
    catalog_download_url: str = ""
    catalog_match_basis: str = ""
    catalog_checked_at: str = ""
    catalog_error: str = ""
    approximate_date: str = ""
    approximate_timestamp: str = ""
    approximate_timestamp_precision: str = ""
    approximate_date_source: str = ""
    approximate_date_evidence: tuple[str, ...] = ()
    approximate_date_mtime_ns: int = 0
    approximate_date_size: int = 0

    def to_json(self) -> dict[str, Any]:
        return dataclasses.asdict(self)

    @classmethod
    def from_json(cls, value: Any, root: str) -> PortableRecord | None:
        if not isinstance(value, dict):
            return None
        raw_reasons = value.get("evidence_reasons", ())
        if not isinstance(raw_reasons, (list, tuple)):
            return None
        raw_date_evidence = value.get("approximate_date_evidence", ())
        if not isinstance(raw_date_evidence, (list, tuple)):
            return None
        try:
            record = cls(
                app_key=str(value["app_key"]),
                name=sanitize_windows_version_resource_text(value["name"], 160),
                version=sanitize_windows_version_resource_text(
                    value.get("version", "Unknown"), 160
                ),
                executable=str(value["executable"]),
                icon_source=str(value.get("icon_source", value["executable"])),
                scan_root=str(value.get("scan_root", root)),
                detected_by=str(value.get("detected_by", "cached folder scan")),
                path_on_path=bool(value.get("path_on_path", False)),
                publisher=sanitize_windows_version_resource_text(
                    value.get("publisher", ""), 160
                ),
                original_filename=sanitize_windows_version_resource_text(
                    value.get("original_filename", ""), 260
                ),
                homepage=str(value.get("homepage", "")),
                detection_confidence=str(value.get("detection_confidence", "known")),
                evidence_score=int(value.get("evidence_score", 100)),
                evidence_reasons=tuple(
                    str(reason)
                    for reason in raw_reasons
                    if str(reason).strip()
                ),
                portable_format=str(value.get("portable_format", "")),
                catalog_package_id=str(value.get("catalog_package_id", "")),
                catalog_name=str(value.get("catalog_name", "")),
                catalog_available_version=str(
                    value.get("catalog_available_version", "")
                ),
                catalog_homepage=str(value.get("catalog_homepage", "")),
                catalog_download_url=str(value.get("catalog_download_url", "")),
                catalog_match_basis=str(value.get("catalog_match_basis", "")),
                catalog_checked_at=str(value.get("catalog_checked_at", "")),
                catalog_error=str(value.get("catalog_error", "")),
                approximate_date=str(value.get("approximate_date", "")),
                approximate_timestamp=str(value.get("approximate_timestamp", "")),
                approximate_timestamp_precision=str(
                    value.get("approximate_timestamp_precision", "")
                ),
                approximate_date_source=str(
                    value.get("approximate_date_source", "")
                ),
                approximate_date_evidence=tuple(
                    str(path)
                    for path in raw_date_evidence[:6]
                    if str(path).strip()
                ),
                approximate_date_mtime_ns=max(
                    0, int(value.get("approximate_date_mtime_ns", 0))
                ),
                approximate_date_size=max(
                    0, int(value.get("approximate_date_size", 0))
                ),
            )
        except (KeyError, TypeError, ValueError):
            return None
        if (
            (record.approximate_date and not re.fullmatch(r"\d{4}-\d{2}-\d{2}", record.approximate_date))
            or (
                record.approximate_timestamp
                and not wall_clock_timestamp_matches_precision(
                    record.approximate_timestamp,
                    record.approximate_timestamp_precision,
                )
            )
            or len(record.approximate_timestamp_precision) > 32
            or (
                not record.approximate_timestamp
                and bool(record.approximate_timestamp_precision)
            )
            or len(record.approximate_date_source) > 500
            or any(len(path) > 4096 for path in record.approximate_date_evidence)
        ):
            return None
        if record.portable_format == "generic PE portable" and (
            _portable_installer_identity_rejection(
                record.executable,
                record.original_filename,
            )
        ):
            return None
        if (
            not record.app_key
            or not record.name
            or not _portable_path_is_within(record.executable, root)
            or not _portable_path_is_within(record.icon_source, root)
            or (
                record.catalog_package_id
                and not valid_package_id(record.catalog_package_id)
            )
            or (
                record.catalog_available_version
                and not valid_version(record.catalog_available_version)
            )
            or record.detection_confidence not in {"known", "high"}
            or not -100 <= record.evidence_score <= 200
            or len(record.evidence_reasons) > 32
        ):
            return None
        return record


@dataclasses.dataclass(frozen=True, slots=True)
class PortableScanResult:
    root: str
    records: tuple[PortableRecord, ...]
    files_checked: int
    directories_checked: int
    metadata_probes: int
    access_errors: int
    truncated: bool
    duration_seconds: float
    review_candidates: int = 0
    rejected_candidates: int = 0
    cancelled: bool = False
    broad_scan: bool = False
    metadata_budget_exhausted: bool = False
    review_samples: tuple[dict[str, Any], ...] = ()
    rejection_reason_counts: tuple[tuple[str, int], ...] = ()
    pruned_directory_reason_counts: tuple[tuple[str, int], ...] = ()


@dataclasses.dataclass(frozen=True, slots=True)
class PortableScanProgress:
    root: str
    apps_found: int
    files_checked: int
    directories_checked: int
    elapsed_seconds: float


@dataclasses.dataclass(frozen=True, slots=True)
class PortableInventoryVerification:
    records: tuple[PortableRecord, ...]
    pruned_records: int = 0
    unreachable_roots: tuple[str, ...] = ()


@dataclasses.dataclass(frozen=True, slots=True)
class PortableLocalRefreshResult:
    records: tuple[PortableRecord, ...]
    checked: int
    version_changes: int
    homepage_changes: int


def portable_catalog_metadata_is_fresh(record: PortableRecord) -> bool:
    if record.catalog_match_basis.startswith(
        "newer version stated in nearby release documentation"
    ):
        # Release clues cached before the identity-bound, adjacent-token parser
        # cannot be trusted for another TTL window after the policy changes.
        return False
    try:
        checked = dt.datetime.fromisoformat(record.catalog_checked_at)
        if checked.tzinfo is None:
            checked = checked.replace(tzinfo=dt.timezone.utc)
        return (
            dt.datetime.now(dt.timezone.utc) - checked
            <= dt.timedelta(seconds=PORTABLE_CATALOG_REFRESH_TTL_SECONDS)
        )
    except (TypeError, ValueError):
        return False


def _replace_file_with_windows_retry(
    source: Path,
    target: Path,
    *,
    replace: Callable[[Path, Path], None] = os.replace,
    pause: Callable[[float], None] = time.sleep,
) -> None:
    """Retry only the brief Windows locks that can race an atomic replace."""

    for attempt in range(len(ATOMIC_REPLACE_RETRY_DELAYS_SECONDS) + 1):
        try:
            replace(source, target)
            return
        except PermissionError as exc:
            transient = (
                os.name == "nt"
                and getattr(exc, "winerror", None)
                in ATOMIC_REPLACE_TRANSIENT_WINERRORS
            )
            if not transient or attempt >= len(ATOMIC_REPLACE_RETRY_DELAYS_SECONDS):
                raise
            pause(ATOMIC_REPLACE_RETRY_DELAYS_SECONDS[attempt])


def atomic_write_text(path: Path, text: str, *, max_bytes: int | None = None) -> None:
    """Durably replace a small UTF-8 text file without exposing a partial write."""

    encoded = text.encode("utf-8")
    if max_bytes is not None and len(encoded) > max_bytes:
        raise ValueError(f"{path.name} exceeded its size limit")
    path.parent.mkdir(parents=True, exist_ok=True)
    temporary = path.with_name(f".{path.name}.{uuid.uuid4().hex}.tmp")
    try:
        with temporary.open("wb") as stream:
            stream.write(encoded)
            stream.flush()
            os.fsync(stream.fileno())
        _replace_file_with_windows_retry(temporary, path)
    finally:
        with contextlib.suppress(OSError):
            temporary.unlink()


# ==================== Portable inventory persistence ====================

class PortableInventoryStore:
    """Small root-indexed, atomically-written cache for user-chosen portable folders."""

    def __init__(self, path: Path | None = None) -> None:
        self.path = path or portable_inventory_path()
        self._lock = threading.RLock()
        # Every mutation advances this in-memory generation. Background release
        # lookups may only write back into the exact inventory snapshot they read.
        self._revision = 0
        self._roots: dict[str, dict[str, Any]] = {}
        self._unreachable_roots: set[str] = set()
        self.warning = ""
        self._load()

    def _load(self) -> None:
        try:
            if self.path.stat().st_size > PORTABLE_CACHE_MAX_BYTES:
                self.warning = "portable inventory cache exceeded its size limit"
                return
            payload = json.loads(self.path.read_text(encoding="utf-8"))
        except FileNotFoundError:
            return
        except (OSError, TypeError, ValueError) as exc:
            self.warning = f"{type(exc).__name__}: {exc}"
            return
        if not isinstance(payload, dict) or payload.get("schema") != PORTABLE_CACHE_SCHEMA:
            self.warning = (
                "portable inventory cache uses older detection rules and will be rebuilt "
                "by the next portable scan"
            )
            return
        roots = payload.get("roots")
        if not isinstance(roots, dict):
            self.warning = "portable inventory cache roots were invalid"
            return
        for raw_key, raw_value in list(roots.items())[:PORTABLE_CACHE_MAX_ROOTS]:
            if not isinstance(raw_value, dict):
                continue
            root = str(raw_value.get("root", ""))
            if not root or _portable_path_key(root) != str(raw_key):
                continue
            raw_entries = raw_value.get("entries", [])
            if not isinstance(raw_entries, list):
                continue
            records = [
                record
                for value in raw_entries[:PORTABLE_CACHE_MAX_ITEMS]
                if (record := PortableRecord.from_json(value, root)) is not None
            ]
            self._roots[str(raw_key)] = {
                "root": root,
                "scanned_at": str(raw_value.get("scanned_at", "")),
                "entries": records,
            }

    def records(self) -> tuple[PortableRecord, ...]:
        """Return the in-memory cache without filesystem I/O."""

        with self._lock:
            records: dict[str, PortableRecord] = {}
            for root_key, root_record in self._roots.items():
                if root_key in self._unreachable_roots:
                    continue
                for record in root_record["entries"]:
                    refreshed = dataclasses.replace(
                        record,
                        path_on_path=executable_folder_on_path(record.executable),
                    )
                    records[_portable_path_key(record.executable)] = refreshed
            return tuple(
                sorted(
                    records.values(),
                    key=lambda record: (record.name.casefold(), record.executable.casefold()),
                )[:PORTABLE_CACHE_MAX_ITEMS]
            )

    def verify_records(self) -> PortableInventoryVerification:
        """Verify cached roots off-thread and prune files missing from reachable roots."""

        with self._lock:
            snapshots = [
                (
                    root_key,
                    str(value["root"]),
                    str(value.get("scanned_at", "")),
                    tuple(value["entries"]),
                )
                for root_key, value in self._roots.items()
            ]
        live_by_root: dict[str, list[PortableRecord]] = {}
        unreachable: set[str] = set()
        pruned = 0
        for root_key, root, _scanned_at, entries in snapshots:
            try:
                root_reachable = Path(root).is_dir()
            except OSError:
                root_reachable = False
            if not root_reachable:
                unreachable.add(root_key)
                continue
            live = [record for record in entries if Path(record.executable).is_file()]
            live_by_root[root_key] = live
            pruned += len(entries) - len(live)
        dirty = False
        with self._lock:
            snapshot_by_key = {
                root_key: (scanned_at, entries)
                for root_key, _root, scanned_at, entries in snapshots
            }
            self._unreachable_roots = {
                root_key for root_key in unreachable if root_key in self._roots
            }
            for root_key, live in live_by_root.items():
                current = self._roots.get(root_key)
                snapshot = snapshot_by_key.get(root_key)
                if (
                    current is None
                    or snapshot is None
                    or str(current.get("scanned_at", "")) != snapshot[0]
                    or tuple(current["entries"]) != snapshot[1]
                ):
                    continue
                if len(live) != len(current["entries"]):
                    current["entries"] = live
                    dirty = True
            if dirty:
                self._revision += 1
                self._save_locked()
        return PortableInventoryVerification(
            self.records(),
            pruned_records=pruned,
            unreachable_roots=tuple(
                root
                for root_key, root, _scanned_at, _entries in snapshots
                if root_key in unreachable
            ),
        )

    def roots(self) -> tuple[str, ...]:
        with self._lock:
            return tuple(str(value["root"]) for value in self._roots.values())

    def catalog_snapshot(self) -> tuple[tuple[PortableRecord, ...], int]:
        """Return portable records and the generation they belong to atomically."""

        with self._lock:
            return self.records(), self._revision

    def clear(self) -> tuple[int, int]:
        """Delete the persisted portable inventory and forget its in-memory records."""

        with self._lock:
            root_count = len(self._roots)
            item_count = sum(len(value["entries"]) for value in self._roots.values())
            try:
                self.path.unlink()
            except FileNotFoundError:
                pass
            # Advance even for an already-empty store: a user-requested clear is
            # an explicit barrier against any catalog worker already in flight.
            self._revision += 1
            self._roots.clear()
            self._unreachable_roots.clear()
            self.warning = ""
            return item_count, root_count

    def replace_root(self, result: PortableScanResult) -> None:
        root_key = _portable_path_key(result.root)
        with self._lock:
            self._revision += 1
            self._unreachable_roots.discard(root_key)
            self._roots[root_key] = {
                "root": result.root,
                "scanned_at": utc_now_iso(),
                "entries": list(result.records),
            }
            if len(self._roots) > PORTABLE_CACHE_MAX_ROOTS:
                oldest = sorted(
                    self._roots,
                    key=lambda key: wall_clock_order_key(
                        self._roots[key].get("scanned_at", "")
                    ),
                )[: len(self._roots) - PORTABLE_CACHE_MAX_ROOTS]
                for key in oldest:
                    self._roots.pop(key, None)
            self._save_locked()

    def forget_executable(self, executable: str | Path) -> bool:
        return bool(self.forget_executables((executable,)))

    def forget_executables(self, executables: Iterable[str | Path]) -> int:
        """Forget selected cached records in one atomic write without touching files."""

        executable_keys = {
            _portable_path_key(executable)
            for executable in executables
            if str(executable).strip()
        }
        if not executable_keys:
            return 0
        cleared = 0
        with self._lock:
            for value in self._roots.values():
                retained = [
                    record
                    for record in value["entries"]
                    if _portable_path_key(record.executable) not in executable_keys
                ]
                cleared += len(value["entries"]) - len(retained)
                if len(retained) != len(value["entries"]):
                    value["entries"] = retained
            if cleared:
                self._revision += 1
                self._save_locked()
        return cleared

    def update_records(
        self,
        records: Sequence[PortableRecord],
        *,
        expected_revision: int | None = None,
    ) -> int | None:
        """Merge catalog fields, or return None when the source snapshot is stale."""

        replacements = {
            _portable_path_key(record.executable): record for record in records
        }
        changed = 0
        with self._lock:
            if expected_revision is not None and expected_revision != self._revision:
                return None
            for value in self._roots.values():
                updated: list[PortableRecord] = []
                for record in value["entries"]:
                    replacement = replacements.get(_portable_path_key(record.executable))
                    if replacement is None:
                        updated.append(record)
                        continue
                    merged = dataclasses.replace(
                        record,
                        catalog_package_id=replacement.catalog_package_id,
                        catalog_name=replacement.catalog_name,
                        catalog_available_version=replacement.catalog_available_version,
                        catalog_homepage=replacement.catalog_homepage,
                        catalog_download_url=replacement.catalog_download_url,
                        catalog_match_basis=replacement.catalog_match_basis,
                        catalog_checked_at=replacement.catalog_checked_at,
                        catalog_error=replacement.catalog_error,
                    )
                    updated.append(merged)
                    changed += int(merged != record)
                value["entries"] = updated
            if changed:
                self._revision += 1
                self._save_locked()
        return changed

    def update_date_evidence(
        self,
        evidence_by_executable: Mapping[
            str, tuple[str, str, str, str, tuple[str, ...]]
        ],
    ) -> int:
        """Persist corroborated portable dates against the executable file version."""

        normalized = {
            _portable_path_key(executable): evidence
            for executable, evidence in evidence_by_executable.items()
        }
        changed = 0
        with self._lock:
            for value in self._roots.values():
                updated: list[PortableRecord] = []
                for record in value["entries"]:
                    evidence = normalized.get(_portable_path_key(record.executable))
                    if evidence is None:
                        updated.append(record)
                        continue
                    try:
                        executable_stat = Path(record.executable).stat()
                    except OSError:
                        updated.append(record)
                        continue
                    observed, timestamp, precision, source, paths = evidence
                    replacement = dataclasses.replace(
                        record,
                        approximate_date=observed,
                        approximate_timestamp=timestamp,
                        approximate_timestamp_precision=precision,
                        approximate_date_source=source,
                        approximate_date_evidence=tuple(paths[:6]),
                        approximate_date_mtime_ns=executable_stat.st_mtime_ns,
                        approximate_date_size=executable_stat.st_size,
                    )
                    updated.append(replacement)
                    changed += int(replacement != record)
                value["entries"] = updated
            if changed:
                self._revision += 1
                self._save_locked()
        return changed

    def update_local_records(
        self,
        records: Sequence[PortableRecord],
        *,
        expected_revision: int,
    ) -> int | None:
        """Replace re-probed local metadata unless the inventory changed meanwhile."""

        replacements = {
            _portable_path_key(record.executable): record for record in records
        }
        changed = 0
        with self._lock:
            if expected_revision != self._revision:
                return None
            for value in self._roots.values():
                updated: list[PortableRecord] = []
                for record in value["entries"]:
                    replacement = replacements.get(_portable_path_key(record.executable))
                    if replacement is None:
                        updated.append(record)
                        continue
                    # Release-catalog evidence belongs to a separate refresh
                    # pipeline. Preserve the current values even though the local
                    # probe began from the same revision.
                    merged = dataclasses.replace(
                        replacement,
                        catalog_package_id=record.catalog_package_id,
                        catalog_name=record.catalog_name,
                        catalog_available_version=record.catalog_available_version,
                        catalog_homepage=record.catalog_homepage,
                        catalog_download_url=record.catalog_download_url,
                        catalog_match_basis=record.catalog_match_basis,
                        catalog_checked_at=record.catalog_checked_at,
                        catalog_error=record.catalog_error,
                    )
                    updated.append(merged)
                    changed += int(merged != record)
                value["entries"] = updated
            if changed:
                self._revision += 1
                self._save_locked()
        return changed

    def _save_locked(self) -> None:
        entries_left = PORTABLE_CACHE_MAX_ITEMS
        roots: dict[str, Any] = {}
        for key, value in sorted(
            self._roots.items(),
            key=lambda pair: wall_clock_order_key(pair[1].get("scanned_at", "")),
            reverse=True,
        ):
            records = list(value["entries"])[:entries_left]
            entries_left -= len(records)
            roots[key] = {
                "root": value["root"],
                "scanned_at": value.get("scanned_at", ""),
                "entries": [record.to_json() for record in records],
            }
            if entries_left <= 0:
                break
        payload = {"schema": PORTABLE_CACHE_SCHEMA, "roots": roots}
        atomic_write_text(
            self.path,
            json.dumps(payload, ensure_ascii=False, indent=2),
            max_bytes=PORTABLE_CACHE_MAX_BYTES,
        )


@contextlib.contextmanager
def _exposed_cloud_placeholders_for_current_thread():
    """Temporarily expose Cloud Files reparse attributes on this scan thread."""

    setter = None
    previous: int | None = None
    if os.name == "nt":
        try:
            ntdll = ctypes.WinDLL("ntdll", use_last_error=True)
            setter = ntdll.RtlSetThreadPlaceholderCompatibilityMode
            setter.argtypes = [ctypes.c_byte]
            setter.restype = ctypes.c_byte
            result = int(setter(2))  # PHCM_EXPOSE_PLACEHOLDERS
            if 0 <= result <= 2:
                previous = result
        except (AttributeError, OSError, TypeError, ValueError):
            setter = None
    try:
        yield previous is not None
    finally:
        if setter is not None and previous is not None:
            with contextlib.suppress(OSError, ValueError):
                setter(previous)


def _scan_portable_root_impl(
    root: str | Path,
    cancel_event: threading.Event | None = None,
    progress_callback: Callable[[PortableScanProgress], None] | None = None,
    *,
    progress_interval_seconds: float = PORTABLE_SCAN_PROGRESS_INTERVAL_SECONDS,
) -> PortableScanResult:
    started = time.perf_counter()
    root_path = Path(root).expanduser().absolute()
    if not root_path.is_dir():
        raise ValueError("portable scan root is not an existing folder")
    if rejection := portable_scan_root_rejection(root_path):
        raise ValueError(rejection)
    protected_roots = portable_system_install_roots()
    broad_scan = portable_scan_is_broad_root(root_path)
    files_checked = 0
    directories_checked = 0
    metadata_probes = 0
    metadata_budget_exhausted = False
    access_errors = 0
    truncated = False
    records: list[PortableRecord] = []
    next_progress_at = started + max(0.0, progress_interval_seconds)
    review_candidates = 0
    rejected_candidates = 0
    cancelled = False
    review_samples: list[dict[str, Any]] = []
    rejection_reason_counts: Counter[str] = Counter()
    pruned_directory_reason_counts: Counter[str] = Counter()
    installed_inventory = PortableInstalledRegistrationIndex.from_inventory(
        WindowsInstalledInventory.load()
    )

    def report_progress_if_due() -> None:
        nonlocal next_progress_at
        if progress_callback is None:
            return
        now = time.perf_counter()
        if now < next_progress_at:
            return
        app_count = len(
            {
                (
                    record.app_key,
                    _portable_path_key(Path(record.executable).parent),
                )
                for record in records
            }
        )
        progress = PortableScanProgress(
            root=str(root_path),
            apps_found=app_count,
            files_checked=min(files_checked, PORTABLE_SCAN_MAX_FILES),
            directories_checked=min(
                directories_checked,
                PORTABLE_SCAN_MAX_DIRECTORIES,
            ),
            elapsed_seconds=now - started,
        )
        with contextlib.suppress(Exception):
            progress_callback(progress)
        next_progress_at = now + max(0.01, progress_interval_seconds)

    def on_error(_error: OSError) -> None:
        nonlocal access_errors
        access_errors += 1

    for current, directories, files in os.walk(root_path, topdown=True, onerror=on_error):
        report_progress_if_due()
        if cancel_event is not None and cancel_event.is_set():
            cancelled = True
            break
        directories_checked += 1
        if directories_checked > PORTABLE_SCAN_MAX_DIRECTORIES:
            truncated = True
            break
        kept_directories: list[str] = []
        for directory in directories:
            candidate = Path(current) / directory
            broad_rejection = portable_broad_directory_rejection(candidate, root_path)
            if broad_rejection:
                pruned_directory_reason_counts[broad_rejection] += 1
                continue
            if (
                directory.casefold() not in PORTABLE_PRUNED_DIRECTORY_NAMES
                and not _portable_path_is_reparse_point(candidate)
                and not any(
                    _portable_path_is_within(candidate, protected)
                    for protected in protected_roots
                )
            ):
                kept_directories.append(directory)
        directories[:] = kept_directories
        if any(filename.casefold() == "appinfo.ini" for filename in files):
            paf = read_portableapps_metadata(Path(current) / "appinfo.ini")
            if paf is not None:
                paf_identity = normalized_package_name(paf.app_id) or hashlib.sha256(
                    paf.app_id.encode("utf-8", errors="replace")
                ).hexdigest()[:20]
                records.append(
                    PortableRecord(
                        app_key=f"paf-{paf_identity[:80]}",
                        name=paf.name,
                        version=paf.version,
                        executable=paf.executable,
                        icon_source=paf.icon_source,
                        scan_root=str(root_path),
                        detected_by="PortableApps.com appinfo.ini",
                        path_on_path=executable_folder_on_path(paf.executable),
                        publisher=paf.publisher,
                        homepage=paf.homepage,
                        detection_confidence="high",
                        evidence_score=120,
                        evidence_reasons=(
                            "valid PortableApps.com Format declaration",
                            "declared launcher remains inside the PortableApps app directory",
                        ),
                        portable_format="PortableApps.com",
                    )
                )
        for filename in files:
            if cancel_event is not None and cancel_event.is_set():
                cancelled = True
                break
            if not filename.casefold().endswith(".exe"):
                continue
            report_progress_if_due()
            executable = Path(current) / filename
            if _portable_path_is_reparse_point(executable):
                continue
            files_checked += 1
            if files_checked > PORTABLE_SCAN_MAX_FILES:
                truncated = True
                break
            signature = portable_signature_for(executable)
            metadata: dict[str, str] = {}
            detected_by = "filename signature"
            if signature is None and metadata_probes < PORTABLE_SCAN_MAX_METADATA_PROBES:
                metadata_probes += 1
                metadata = windows_file_version_strings(executable)
                signature = portable_signature_for(executable, metadata)
                detected_by = "Windows version resource"
            elif signature is None:
                metadata_budget_exhausted = True
            elif signature is not None and metadata_probes < PORTABLE_SCAN_MAX_METADATA_PROBES:
                metadata_probes += 1
                metadata = windows_file_version_strings(executable)
            if signature is not None and not _portable_signature_filename_matches(
                signature, executable
            ):
                # Version resources can identify an installed/setup executable as
                # the same product. Built-in portable signatures require their
                # deliberately narrow executable filename boundary.
                signature = None
            if signature is None:
                if not metadata:
                    continue
                evidence = portable_generic_evidence(
                    executable,
                    metadata,
                    installed_inventory,
                    scan_root=root_path,
                    broad_scan=broad_scan,
                )
                if evidence.confidence != "high":
                    review_candidates += int(evidence.confidence == "review")
                    rejected_candidates += int(evidence.confidence == "rejected")
                    if evidence.confidence == "rejected":
                        rejection_reason_counts.update(evidence.reasons)
                    elif (
                        evidence.confidence == "review"
                        and len(review_samples) < PORTABLE_SCAN_DIAGNOSTIC_SAMPLE_MAX
                    ):
                        review_samples.append(
                            {
                                "name": evidence.name,
                                "publisher": evidence.publisher,
                                "executable": str(executable),
                                "score": evidence.score,
                                "reasons": list(evidence.reasons),
                            }
                        )
                    continue
                icon_source = choose_portable_icon_source(
                    executable,
                    display_name=evidence.name,
                )
                records.append(
                    PortableRecord(
                        app_key=_portable_generic_app_key(
                            evidence.name,
                            evidence.publisher,
                        ),
                        name=evidence.name,
                        version=_portable_version(metadata, filename),
                        executable=str(executable),
                        icon_source=str(icon_source),
                        scan_root=str(root_path),
                        detected_by="high-confidence PE evidence",
                        path_on_path=executable_folder_on_path(executable),
                        publisher=evidence.publisher,
                        original_filename=evidence.original_filename,
                        detection_confidence="high",
                        evidence_score=evidence.score,
                        evidence_reasons=evidence.reasons,
                        portable_format="generic PE portable",
                    )
                )
                continue
            if rejection := portable_candidate_rejection(
                executable,
                metadata,
                installed_inventory,
                broad_scan=broad_scan,
            ):
                rejected_candidates += 1
                rejection_reason_counts[rejection] += 1
                continue
            icon_source = choose_portable_icon_source(executable, signature)
            records.append(
                PortableRecord(
                    app_key=signature.key,
                    name=signature.display_name,
                    version=_portable_version(metadata, filename),
                    executable=str(executable),
                    icon_source=str(icon_source),
                    scan_root=str(root_path),
                    detected_by=detected_by,
                    path_on_path=executable_folder_on_path(executable),
                    publisher=str(metadata.get("CompanyName", "")).strip(),
                    original_filename=str(metadata.get("OriginalFilename", "")).strip(),
                    homepage=signature.homepage,
                    detection_confidence="known",
                    evidence_score=110,
                    evidence_reasons=(
                        f"matched the built-in {signature.display_name} portable signature",
                    ),
                    portable_format="known portable signature",
                )
            )
            if len(records) >= PORTABLE_CACHE_MAX_ITEMS:
                truncated = True
                break
        if truncated or cancelled:
            break
    report_progress_if_due()
    unique_records: dict[str, PortableRecord] = {}
    for record in records:
        key = _portable_path_key(record.executable)
        previous = unique_records.get(key)
        if previous is None or record.evidence_score > previous.evidence_score:
            unique_records[key] = record
    # One app folder can carry a GUI executable plus CLI/test/helper siblings
    # with identical product metadata. Present the best representative while
    # preserving genuinely separate copies in different folders.
    representatives: dict[tuple[str, str], PortableRecord] = {}
    for record in unique_records.values():
        key = (
            record.app_key,
            _portable_path_key(Path(record.executable).parent),
        )
        previous = representatives.get(key)
        if previous is not None and _portable_representative_rank(
            previous
        ) >= _portable_representative_rank(record):
            continue
        representatives[key] = record
    return PortableScanResult(
        root=str(root_path),
        records=tuple(
            sorted(representatives.values(), key=lambda record: record.executable.casefold())
        ),
        files_checked=min(files_checked, PORTABLE_SCAN_MAX_FILES),
        directories_checked=min(directories_checked, PORTABLE_SCAN_MAX_DIRECTORIES),
        metadata_probes=metadata_probes,
        access_errors=access_errors,
        truncated=truncated,
        duration_seconds=time.perf_counter() - started,
        review_candidates=review_candidates,
        rejected_candidates=rejected_candidates,
        cancelled=cancelled,
        broad_scan=broad_scan,
        metadata_budget_exhausted=metadata_budget_exhausted,
        review_samples=tuple(review_samples),
        rejection_reason_counts=tuple(rejection_reason_counts.most_common()),
        pruned_directory_reason_counts=tuple(
            pruned_directory_reason_counts.most_common()
        ),
    )


def scan_portable_root(
    root: str | Path,
    cancel_event: threading.Event | None = None,
    progress_callback: Callable[[PortableScanProgress], None] | None = None,
    *,
    progress_interval_seconds: float = PORTABLE_SCAN_PROGRESS_INTERVAL_SECONDS,
) -> PortableScanResult:
    with _exposed_cloud_placeholders_for_current_thread():
        return _scan_portable_root_impl(
            root,
            cancel_event,
            progress_callback,
            progress_interval_seconds=progress_interval_seconds,
        )


def icon_cache_dir() -> Path:
    return app_data_dir() / "icon-cache"


def icon_catalog_path() -> Path:
    return icon_cache_dir() / ICON_CATALOG_FILENAME


def clear_generated_icon_cache_files() -> tuple[int, int]:
    """Clear flat generated artwork only; never traverse folders or filesystem links."""

    root = icon_cache_dir()
    try:
        root_stat = root.lstat()
    except FileNotFoundError:
        return 0, 0
    if not stat.S_ISDIR(root_stat.st_mode) or getattr(root_stat, "st_file_attributes", 0) & 0x400:
        raise OSError("The icon cache is not a regular directory; nothing was deleted")
    families = (
        "iconpack-",
        "appicon-", "detailsicon-", "rawicon-", "displayicon-",
        "provider-alpha-dot-", "provider-minus-",
        "vectoricon-",
    )
    removed = retained = 0
    with os.scandir(root) as entries:
        # Finish Windows directory enumeration before deleting entries: mutating
        # a live enumeration can skip files in a large cache without an error.
        candidates = list(entries)
    for entry in candidates:
        name = entry.name
        generated = name == ICON_CATALOG_FILENAME or (
            name.lstrip(".").startswith(families)
            and name.endswith((".png", ".json", ".tmp", ".bin"))
        ) or (name.startswith(f".{ICON_CATALOG_FILENAME}.") and name.endswith(".tmp"))
        if not generated:
            retained += 1
            continue
        try:
            entry_stat = entry.stat(follow_symlinks=False)
            if (
                not stat.S_ISREG(entry_stat.st_mode)
                or getattr(entry_stat, "st_file_attributes", 0) & 0x400
            ):
                retained += 1
                continue
            Path(entry.path).unlink()
            removed += 1
        except OSError:
            retained += 1
    return removed, retained


def icon_catalog_compatibility() -> dict[str, Any]:
    return {
        "schema": ICON_CATALOG_SCHEMA,
        "app_icon_prefix": APP_ICON_CACHE_PREFIX,
        "detail_icon_prefix": DETAIL_ICON_CACHE_PREFIX,
        "raw_icon_prefix": RAW_ICON_CACHE_PREFIX,
        "display_icon_prefix": DISPLAY_ICON_CACHE_PREFIX,
        "extraction_revision": WINDOWS_ICON_EXTRACTION_REVISION,
        "outline_revision": ADAPTIVE_OUTLINE_REVISION,
        "extraction_policy_revision": ICON_EXTRACTION_POLICY_REVISION,
        "source_selection_revision": ICON_SOURCE_SELECTION_REVISION,
        "compact_revision": COMPACT_ICON_REVISION,
    }


def compact_gallery_size(resource_size: int) -> int:
    return max(1, round(resource_size * PACKAGE_GALLERY_COMPACT_SCALE))


def compact_icon_path(display_path: Path, resource_size: int) -> Path:
    return display_path.with_name(f"{display_path.stem}-compact-{resource_size}.png")


def compact_icon_catalog_record(record: Mapping[str, Any]) -> dict[str, Any] | None:
    """Worker-only: derive exact NN pixels and bind them to this master generation."""
    root = icon_cache_dir()
    parent = root / record["display"]
    resource_size = int(record["size"])
    target = compact_gallery_size(resource_size)
    path = compact_icon_path(parent, resource_size)
    metadata_path = icon_render_metadata_path(path)
    binding = {"parent": parent.name, "parent_stat": record["display_stat"],
               "resource_size": resource_size, "revision": COMPACT_ICON_REVISION}
    try:
        if metadata_path.stat().st_size > 32_768:
            raise ValueError("compact metadata too large")
        metadata = json.loads(metadata_path.read_text(encoding="utf-8"))
        if any(metadata.get(key) != value for key, value in binding.items()):
            raise ValueError("compact parent changed")
        info = path.stat()
        if metadata.get("display_stat") != [info.st_mtime_ns, info.st_size]:
            raise ValueError("compact rendition changed")
    except (OSError, ValueError, TypeError, AttributeError):
        decoded = read_png_rgba(parent)
        if decoded is None:
            return None
        width, height, rows = decoded
        rows = _scale_rgba_nearest(rows, width, height, target, target)
        write_rgba_png(path, target, target, rows)
        info = path.stat()
        metadata = {**binding, "display_stat": [info.st_mtime_ns, info.st_size]}
        write_icon_render_metadata(path, metadata)
    # A source replacement racing the writer must not publish mixed generations.
    parent_stat = parent.stat()
    if [parent_stat.st_mtime_ns, parent_stat.st_size] != record["display_stat"]:
        return None
    return {**record, **binding, "raw": parent.name, "raw_stat": record["display_stat"],
            "display": path.name, "display_stat": [info.st_mtime_ns, info.st_size],
            "size": target, "dims": [target, target], "has_visual_detail": True}


def _icon_png_integrity(data: bytes) -> bool:
    """Check PNG chunk boundaries/CRCs without inflating pixels; worker-only."""
    if not data.startswith(PNG_SIGNATURE):
        return False
    position = len(PNG_SIGNATURE)
    while position + 12 <= len(data):
        length = struct.unpack_from(">I", data, position)[0]
        end = position + 8 + length
        if end + 4 > len(data):
            return False
        if zlib.crc32(data[position + 4:end]) & 0xffffffff != struct.unpack_from(">I", data, end)[0]:
            return False
        if data[position + 4:position + 8] == b"IEND":
            return length == 0 and end + 4 == len(data)
        position = end + 4
    return False


class IconPack:
    """Immutable accelerator, fully read and validated on a loader thread.

    Entries use display filenames so package aliases share one payload. Records
    carry the catalog's file generation, dimensions and visual-detail verdict.
    No mapping, file handle or lazy filesystem operation crosses into Tk.
    """

    def __init__(self, path: Path, size: int, mode: str) -> None:
        with path.open("rb") as stream:
            length = os.fstat(stream.fileno()).st_size
            if not len(ICON_PACK_MAGIC) + 8 < length <= ICON_CATALOG_BLOB_BUDGET_BYTES:
                raise ValueError("icon pack size out of bounds")
            data = bytearray(length)
            if stream.readinto(data) != length:
                raise ValueError("truncated icon pack")
        start = len(ICON_PACK_MAGIC)
        if data[:start] != ICON_PACK_MAGIC:
            raise ValueError("icon pack magic mismatch")
        index_length, checksum = struct.unpack_from("<II", data, start)
        base = start + 8 + index_length
        if not 0 < index_length <= ICON_CATALOG_MAX_BYTES or base > len(data):
            raise ValueError("icon pack index out of bounds")
        encoded = data[start + 8:base]
        if zlib.crc32(encoded) & 0xffffffff != checksum:
            raise ValueError("icon pack index checksum mismatch")
        index = json.loads(encoded)
        if (not isinstance(index, dict) or index.get("revision") != icon_catalog_compatibility()
                or index.get("size") != size or index.get("mode") != mode):
            raise ValueError("icon pack compatibility mismatch")
        entries, dims = index.get("entries"), index.get("dims")
        if (not isinstance(entries, dict) or not isinstance(dims, dict)
                or entries.keys() != dims.keys() or len(entries) > ICON_CATALOG_MAX_ENTRIES * 3):
            raise ValueError("invalid icon pack entries")
        spans = []
        for key, record in entries.items():
            if (not _icon_catalog_cache_name(key) or not isinstance(record, list) or len(record) != 4
                    or not all(type(n) is int for n in record[:3])):
                raise ValueError("invalid icon pack record")
            offset, count, flags, stamp = record
            dimensions = dims[key]
            if (offset < 0 or not 0 < count <= ICON_CATALOG_SINGLE_BLOB_MAX_BYTES
                    or offset + count > len(data) - base or flags not in (0, 1)
                    or not isinstance(stamp, list) or len(stamp) != 2
                    or not all(type(n) is int and n >= 0 for n in stamp)
                    or not isinstance(dimensions, list) or len(dimensions) != 2
                    or not all(type(n) is int and 0 < n <= 1024 for n in dimensions)):
                raise ValueError("icon pack span or dimensions out of bounds")
            spans.append((offset, offset + count))
        spans.sort()
        if any(left[1] > right[0] for left, right in zip(spans, spans[1:])):
            raise ValueError("overlapping icon pack spans")
        self.index = index
        self._data, self._base = data, base

    def payload(self, name: str, stamp: Sequence[int]) -> bytes | None:
        record = self.index["entries"].get(name)
        if record is None or not record[2] & 1 or record[3] != list(stamp):
            return None
        offset, count = record[:2]
        data = bytes(self._data[self._base + offset:self._base + offset + count])
        return data if _icon_png_integrity(data) else None


def write_icon_packs(entries: Mapping[str, Mapping[str, Any]], mode: str) -> None:
    """Worker-only, whole-file immutable generations; renderer PNGs remain authoritative."""
    groups: dict[int, dict[str, Mapping[str, Any]]] = {}
    root = icon_cache_dir()
    for entry in entries.values():
        for field in ("list", "compact", "details"):
            record = entry.get(field)
            if isinstance(record, dict):
                groups.setdefault(int(record["size"]), {})[record["display"]] = record
    for size, records in groups.items():
        payload = bytearray()
        index: dict[str, Any] = {"revision": icon_catalog_compatibility(), "size": size,
                                 "mode": mode, "entries": {}, "dims": {}}
        for name, record in records.items():
            path = root / name
            try:
                if path.stat().st_size > ICON_CATALOG_SINGLE_BLOB_MAX_BYTES:
                    continue
                data = path.read_bytes()
                info = path.stat()
            except OSError:
                continue
            if ([info.st_mtime_ns, info.st_size] != record["display_stat"]
                    or not _icon_png_integrity(data)):
                continue
            header = png_header_fast(data)
            if header is None or max(header.dimensions) > 1024:
                continue
            if len(payload) + len(data) > ICON_CATALOG_BLOB_BUDGET_BYTES - ICON_CATALOG_MAX_BYTES:
                break  # Resource bound for corrupt/exceptionally large caches, not tier priority.
            index["entries"][name] = [len(payload), len(data), int(record.get("has_visual_detail", True)), record["display_stat"]]
            index["dims"][name] = list(header.dimensions)
            payload.extend(data)
        encoded = json.dumps(index, separators=(",", ":"), sort_keys=True).encode("utf-8")
        if len(encoded) > ICON_CATALOG_MAX_BYTES:
            continue
        # time_ns + PID/thread identity avoids two instances choosing one destination.
        destination = root / (f"iconpack-{DISPLAY_ICON_CACHE_PREFIX}{size}px-{mode}-"
                              f"{time.time_ns():020d}-{os.getpid()}-{threading.get_ident()}.bin")
        write_png_bytes(destination, ICON_PACK_MAGIC + struct.pack("<II", len(encoded),
                        zlib.crc32(encoded) & 0xffffffff) + encoded + payload)


def load_icon_packs(mode: str, sizes: Sequence[int] | None = None) -> tuple[dict[int, IconPack], list[str]]:
    """Startup-only cleanup and bounded sequential reads, entirely off-thread."""
    groups: dict[int, list[Path]] = {}
    for path in icon_cache_dir().glob(f"iconpack-{DISPLAY_ICON_CACHE_PREFIX}*px-{mode}-*.bin"):
        match = re.fullmatch(r"iconpack-" + re.escape(DISPLAY_ICON_CACHE_PREFIX)
                             + r"(\d+)px-" + re.escape(mode) + r"-\d+-\d+-\d+\.bin", path.name)
        if match and 8 <= int(match[1]) <= 1024 and (sizes is None or int(match[1]) in sizes):
            groups.setdefault(int(match[1]), []).append(path)
    packs, errors = {}, []
    for size, paths in groups.items():
        paths.sort(reverse=True)
        for stale in paths[2:]:
            with contextlib.suppress(OSError):
                stale.unlink()
        try:
            packs[size] = IconPack(paths[0], size, mode)
        except (OSError, ValueError, TypeError, KeyError, struct.error) as exc:
            errors.append(f"{paths[0].name}: {exc}")
    return packs, errors


def _icon_catalog_cache_name(value: Any) -> str:
    name = str(value or "")
    if not name or Path(name).name != name or "/" in name or "\\" in name:
        return ""
    return name


def icon_catalog_miss_is_current(entry: Mapping[str, Any], field: str) -> bool:
    try:
        remaining = float(entry.get(f"{field}_unavailable_until", 0)) - time.time()
    except (TypeError, ValueError):
        return False
    return bool(entry.get(f"{field}_unavailable")) and 0 <= remaining <= ICON_RENDER_MISS_TTL_SECONDS


def changed_icon_catalog_keys(
    entries: Mapping[str, Mapping[str, Any]], items: Sequence[UpdateItem],
) -> set[str]:
    """Validate cached source versions once per path, off the GUI thread."""

    current = {item.key: item for item in items}
    source_stats: dict[str, list[int] | None] = {}
    changed: set[str] = set()
    for key, entry in entries.items():
        item = current.get(key)
        identity = list(item_icon_identity(item)) if item is not None else None
        if identity is not None:
            identity[2] = known_product_variant_name(item.provider, item.package_id, item.name)
        if item is not None and (
            entry.get("identity") != identity
            or (entry.get("version") and entry["version"] != item.current)
        ):
            changed.add(key)
            continue
        source = str(entry.get("source") or "")
        if not source:
            try:
                age = time.time() - float(entry.get("source_checked_at", 0))
            except (TypeError, ValueError):
                age = -1
            if not 0 <= age <= ICON_CATALOG_NEGATIVE_SOURCE_TTL_SECONDS:
                changed.add(key)
            continue
        if source not in source_stats:
            try:
                source_stat = Path(source).stat()
                source_stats[source] = [source_stat.st_mtime_ns, source_stat.st_size]
            except OSError:
                source_stats[source] = None
        if source_stats[source] is None or source_stats[source] != entry.get("source_stat"):
            changed.add(key)
        elif any(entry.get(f"{field}_unavailable") and not icon_catalog_miss_is_current(entry, field)
                 for field in ("list", "details")):
            changed.add(key)
    return changed


def _icon_catalog_record_paths(
    record: Any, file_stats: Mapping[str, os.stat_result] | None = None,
) -> tuple[Path, Path, os.stat_result, os.stat_result] | None:
    if not isinstance(record, dict):
        return None
    raw_name = _icon_catalog_cache_name(record.get("raw"))
    display_name = _icon_catalog_cache_name(record.get("display"))
    if not raw_name or not display_name:
        return None
    root = icon_cache_dir()
    raw_path = root / raw_name
    display_path = root / display_name
    try:
        raw_stat = file_stats[raw_name] if file_stats is not None else raw_path.stat()
        display_stat = file_stats[display_name] if file_stats is not None else display_path.stat()
        expected_raw = record["raw_stat"]
        expected_display = record["display_stat"]
        if [raw_stat.st_mtime_ns, raw_stat.st_size] != [
            int(expected_raw[0]),
            int(expected_raw[1]),
        ] or [display_stat.st_mtime_ns, display_stat.st_size] != [
            int(expected_display[0]),
            int(expected_display[1]),
        ]:
            return None
    except (OSError, TypeError, ValueError, IndexError, KeyError):
        return None
    return raw_path, display_path, raw_stat, display_stat


def load_icon_catalog_and_blobs(
    mode: str = "neutral", sizes: Sequence[int] | None = None,
) -> tuple[dict[str, dict[str, Any]], dict[str, bytes], str]:
    """Validate the compact catalog and warm bounded PNG bytes off Tk's thread."""

    path = icon_catalog_path()
    try:
        if path.stat().st_size > ICON_CATALOG_MAX_BYTES:
            return {}, {}, "catalog exceeded its size limit"
        payload = json.loads(path.read_text(encoding="utf-8"))
    except FileNotFoundError:
        return {}, {}, ""
    except (OSError, TypeError, ValueError) as exc:
        return {}, {}, f"{type(exc).__name__}: {exc}"
    if not isinstance(payload, dict):
        return {}, {}, "catalog root was not an object"
    compatibility = icon_catalog_compatibility()
    if any(payload.get(key) != value for key, value in compatibility.items()):
        return {}, {}, "catalog revision did not match this build"
    raw_entries = payload.get("entries")
    if not isinstance(raw_entries, dict):
        return {}, {}, "catalog entries were not an object"

    packs, pack_errors = load_icon_packs(mode, sizes)
    # Windows DirEntry.stat uses directory enumeration metadata, avoiding repeated opens.
    file_stats = {}
    with os.scandir(icon_cache_dir()) as listing:
        for file in listing:
            if file.name.endswith(".png"):
                with contextlib.suppress(OSError):
                    file_stats[file.name] = file.stat(follow_symlinks=False)
    source_stats: dict[str, os.stat_result] = {}
    now = time.time()
    entries: dict[str, dict[str, Any]] = {}
    list_blob_paths: list[Path] = []
    detail_blob_paths: list[Path] = []
    for raw_key, raw_entry in raw_entries.items():
        key = str(raw_key)
        if not key or len(key) > 2048 or not isinstance(raw_entry, dict):
            continue
        identity = raw_entry.get("identity")
        if (
            not isinstance(identity, list)
            or len(identity) != 5
            or not all(isinstance(value, str) and len(value) <= 4096 for value in identity)
        ):
            continue
        source_text = str(raw_entry.get("source") or "")
        if len(source_text) > 32_768:
            continue
        source: Path | None = Path(source_text) if source_text else None
        if source is not None:
            source_stat = raw_entry.get("source_stat")
            try:
                stat = source_stats.get(source_text)
                if stat is None:
                    stat = source_stats[source_text] = source.stat()
                expected_mtime, expected_size = int(source_stat[0]), int(source_stat[1])
            except (OSError, TypeError, ValueError, IndexError):
                continue
            if stat.st_mtime_ns != expected_mtime or stat.st_size != expected_size:
                continue
        else:
            try:
                checked_at = float(raw_entry.get("source_checked_at", 0.0))
            except (TypeError, ValueError):
                continue
            if not 0 <= now - checked_at <= ICON_CATALOG_NEGATIVE_SOURCE_TTL_SECONDS:
                continue
        branding = registered_brand_icon_path(identity[0], identity[1], identity[3])
        if preferred := preferred_installed_shell_icon(identity[0], identity[1], identity[4]):
            if os.path.normcase(source_text) != os.path.normcase(str(preferred)):
                continue  # This game's registered ICO is not its preferred shell artwork.
        if (Path(source_text).suffix.casefold() in {".exe", ".dll"}
                and (raw_entry.get("list") or raw_entry.get("details"))
                and raw_entry.get("pe_group_revision") != "default-v1"):
            continue  # Rebuild older cross-group choices once; other formats stay warm.
        if (raw_entry.get("appx_selection_revision") != "manifest-v1"
                and identity[0].casefold() == MICROSOFT_STORE_PROVIDER_KEY
                and identity[1].casefold().startswith("msix\\")):
            best = resolve_icon_source_fields(identity[0], identity[3], identity[1], identity[4], identity[2])
            if best is not None and os.path.normcase(str(best)) != os.path.normcase(source_text):
                continue  # Retire only obsolete Store source choices, not all artwork.
        if branding is not None and os.path.normcase(source_text) != os.path.normcase(str(branding)):
            continue  # Retire only an older source miss/choice for this registered artwork.
        if (source_text and raw_entry.get("placeholder_checked") != "opaque-alpha-v3"
                and cached_source_has_windows_placeholder(Path(source_text))):
            continue  # Re-resolve this source only; preserve unrelated warm artwork.
        try:
            seen_at = float(raw_entry.get("seen_at", 0.0))
        except (TypeError, ValueError):
            seen_at = 0.0
        entry: dict[str, Any] = {
            "identity": list(identity),
            "version": str(raw_entry.get("version") or ""),
            "source": source_text,
            "source_stat": raw_entry.get("source_stat"),
            "source_checked_at": raw_entry.get("source_checked_at", 0.0),
            "seen_at": seen_at,
            "placeholder_checked": "opaque-alpha-v3",
            "appx_selection_revision": "manifest-v1",
            "pe_group_revision": "default-v1",
        }
        for field, destinations in (("list", list_blob_paths), ("compact", list_blob_paths), ("details", detail_blob_paths)):
            if icon_catalog_miss_is_current(raw_entry, field):
                entry[f"{field}_unavailable"] = True
                entry[f"{field}_unavailable_until"] = raw_entry[f"{field}_unavailable_until"]
            record = raw_entry.get(field)
            if isinstance(record, dict) and record.get("has_visual_detail") is False:
                continue
            paths = _icon_catalog_record_paths(record, file_stats)
            if paths is None:
                continue
            try:
                size = int(record.get("size", 0))
            except (TypeError, ValueError):
                continue
            if not 8 <= size <= 1024:
                continue
            if sizes is not None and size not in sizes:
                continue
            dims = record.get("dims", [size, size])
            if (not isinstance(dims, list) or len(dims) != 2
                    or not all(type(value) is int and 0 < value <= 1024 for value in dims)):
                continue
            raw_path, display_path, raw_stat, display_stat = paths
            if field == "compact":
                parent = raw_entry.get("details", {})
                if (record.get("parent") != parent.get("display")
                        or record.get("parent_stat") != parent.get("display_stat")
                        or record.get("resource_size") != parent.get("size")
                        or record.get("revision") != COMPACT_ICON_REVISION):
                    continue
            entry[field] = {
                **record,
                "dims": dims,
                "size": size,
                "raw": raw_path.name,
                "display": display_path.name,
                "raw_stat": [raw_stat.st_mtime_ns, raw_stat.st_size],
                "display_stat": [
                    display_stat.st_mtime_ns,
                    display_stat.st_size,
                ],
            }
            destinations.append(display_path)
        entries[key] = entry

    blobs: dict[str, bytes] = {}
    used_bytes = 0
    packed_records = {str(icon_cache_dir() / record["display"]): record
                      for entry in entries.values() for field in ("list", "compact", "details")
                      if isinstance((record := entry.get(field)), dict)}
    # Files remain the fallback for missing, stale or corrupt pack entries.
    for display_path in (*list_blob_paths, *detail_blob_paths):
        path_key = str(display_path)
        if path_key in blobs:
            continue
        try:
            size = packed_records[path_key]["display_stat"][1]
            if (
                size <= len(PNG_SIGNATURE)
                or size > ICON_CATALOG_SINGLE_BLOB_MAX_BYTES
                or used_bytes + size > ICON_CATALOG_BLOB_BUDGET_BYTES
            ):
                continue
            record = packed_records[path_key]
            pack = packs.get(record["size"])
            data = pack.payload(display_path.name, record["display_stat"]) if pack else None
            if data is None:
                data = display_path.read_bytes()
        except OSError:
            continue
        if not data.startswith(PNG_SIGNATURE):
            continue
        blobs[path_key] = data
        used_bytes += len(data)
    return entries, blobs, "; ".join(pack_errors)


def prepared_icon_evidence(source: Path, raw_path: Path, display_path: Path) -> dict[str, Any] | None:
    """Worker-only: retain the established metadata size limit and allowed fields."""
    if not display_path.exists():
        return None
    evidence: dict[str, Any] = {
        "source_file": str(source),
        "raw_png": str(raw_path),
        "generated_png": str(display_path),
        "metadata_ready": False,
    }
    metadata_path = icon_render_metadata_path(display_path)
    try:
        if metadata_path.stat().st_size > 32_768:
            return evidence
        metadata = json.loads(metadata_path.read_text(encoding="utf-8"))
    except (OSError, ValueError, TypeError):
        return evidence
    if not isinstance(metadata, dict) or metadata.get("schema") != 1:
        return evidence
    allowed_fields = {
        "source_canvas_width",
        "source_canvas_height",
        "source_visible_width",
        "source_visible_height",
        "source_has_explicit_alpha_channel",
        "source_uses_transparency",
        "source_uses_partial_alpha",
        "alpha_cleanup_applied",
        "upscaled",
        "upscale_scale_x",
        "upscale_scale_y",
        "rendered_art_width",
        "rendered_art_height",
        "adaptive_outline_applied",
        "adaptive_outline_tone",
        "output_width",
        "output_height",
        "normalized_with_gdiplus",
        "native_ico_frame_width",
        "native_ico_frame_height",
        "native_ico_frame_preserved",
    }
    evidence.update({key: metadata[key] for key in allowed_fields if key in metadata})
    evidence["metadata_ready"] = icon_render_metadata_is_current(metadata)
    return evidence


def prepared_details_icon_payload(
    items: Sequence[UpdateItem], source: Path, list_size: int, details_size: int,
) -> tuple[dict[str, dict[str, Any]], dict[str, bytes]]:
    """Worker-only: validate prepared records, then read bounded bytes shared by aliases."""
    entries = build_icon_catalog_entries(
        items, {item.key: source for item in items}, list_size, details_size, {}, full_inventory=False)
    blobs: dict[str, bytes] = {}
    evidence_by_path: dict[str, dict[str, Any] | None] = {}
    for entry, field in ((entry, field) for entry in entries.values() for field in ("details", "compact")):
        record = entry.get(field)
        if not isinstance(record, dict):
            continue
        path = icon_cache_dir() / record["display"]
        if str(path) not in evidence_by_path:
            evidence_by_path[str(path)] = prepared_icon_evidence(source, icon_cache_dir() / record["raw"], path)
        if field == "details":
            entry["details_evidence"] = evidence_by_path[str(path)]
        if str(path) in blobs:
            continue
        try:
            expected = record["display_stat"]
            if not len(PNG_SIGNATURE) < expected[1] <= ICON_CATALOG_SINGLE_BLOB_MAX_BYTES:
                continue
            with path.open("rb") as stream:
                data = stream.read(ICON_CATALOG_SINGLE_BLOB_MAX_BYTES + 1)
            final_stat = path.stat()
            if ([final_stat.st_mtime_ns, final_stat.st_size] != expected or len(data) != expected[1]
                    or not data.startswith(PNG_SIGNATURE)
                    or sum(map(len, blobs.values())) + len(data) > ICON_CATALOG_BLOB_BUDGET_BYTES):
                continue
        except OSError:
            continue
        blobs[str(path)] = data
    return entries, blobs


def write_icon_catalog(entries: Mapping[str, Mapping[str, Any]]) -> None:
    """Atomically persist a bounded, inspectable accelerator index."""

    destination = icon_catalog_path()
    destination.parent.mkdir(parents=True, exist_ok=True)
    payload = {
        **icon_catalog_compatibility(),
        "written_at": time.time(),
        "entries": dict(entries),
    }
    encoded = json.dumps(payload, ensure_ascii=False, sort_keys=True, separators=(",", ":"))
    if len(encoded.encode("utf-8")) > ICON_CATALOG_MAX_BYTES:
        raise ValueError("icon catalog exceeded its size limit")
    temporary = destination.with_name(
        f".{destination.name}.{os.getpid()}.{threading.get_ident()}.tmp"
    )
    try:
        temporary.write_text(encoded, encoding="utf-8")
        os.replace(temporary, destination)
    finally:
        with contextlib.suppress(OSError):
            temporary.unlink()


def icon_catalog_list_display_paths(
    entries: Mapping[str, Mapping[str, Any]],
    valid_paths: Set[str],
) -> dict[tuple[str, int], str]:
    """Index already-validated list artwork without touching the filesystem."""

    paths: dict[tuple[str, int], str] = {}
    root = icon_cache_dir()
    for item_key, entry in entries.items():
        record = entry.get("list")
        if not isinstance(record, Mapping) or not record.get("display"):
            continue
        try:
            size = int(record["size"])
        except (KeyError, TypeError, ValueError):
            continue
        display_path = str(root / str(record["display"]))
        if size > 0 and display_path in valid_paths:
            paths[(str(item_key), size)] = display_path
    return paths


def build_icon_catalog_entries(
    items: Sequence[UpdateItem],
    sources: Mapping[str, Path | None],
    list_size: int,
    details_size: int,
    existing: Mapping[str, Mapping[str, Any]],
    *,
    full_inventory: bool,
) -> dict[str, dict[str, Any]]:
    """Build a catalog snapshot off the UI thread from immutable scan state."""

    now = time.time()
    current_keys = {item.key for item in items}
    entries = {
        str(key): dict(value) for key, value in existing.items()
        if not full_inventory or key in current_keys
    }
    render_records: dict[tuple[Path, int], dict[str, Any] | None] = {}
    render_misses: dict[tuple[Path, int], float] = {}
    for item in items:
        identity = list(item_icon_identity(item))
        previous = entries.get(item.key, {})
        if item.key not in sources:
            # A partial checkpoint must not turn an unresolved lookup into a
            # persisted negative result. Retain only matching prior evidence.
            if previous.get("identity") != identity:
                entries.pop(item.key, None)
            continue
        source = sources[item.key]
        entry: dict[str, Any] = {
            "identity": identity,
            "version": item.current,
            "source": str(source) if source is not None else "",
            "source_stat": None,
            "source_checked_at": 0.0,
            "seen_at": now,
        }
        if source is None:
            if previous.get("identity") == identity and not previous.get("source"):
                entry["source_checked_at"] = previous.get("source_checked_at", now)
            else:
                entry["source_checked_at"] = now
            entries[item.key] = entry
            continue
        try:
            stat = source.stat()
        except OSError:
            entries.pop(item.key, None)
            continue
        entry["source_stat"] = [stat.st_mtime_ns, stat.st_size]
        entry["appx_selection_revision"] = "manifest-v1"
        entry["pe_group_revision"] = "default-v1"
        entry["placeholder_checked"] = (
            previous.get("placeholder_checked", "") if previous.get("source") == str(source)
            and previous.get("source_stat") == entry["source_stat"]
            else ""
        )
        for field, size in (("list", list_size), ("details", details_size)):
            raw_path = (
                package_icon_cache_path_for_fields(
                    item.provider,
                    item.package_id,
                    item.name,
                    source,
                    size,
                    "catalog",
                )
                if field == "list"
                else details_icon_cache_path_for_fields(
                    item.provider,
                    item.package_id,
                    item.name,
                    source,
                    size,
                )
            )
            render_key = (raw_path, size)
            if render_key not in render_records and render_key not in render_misses:
                render_is_current = rendered_icon_cache_is_current(raw_path, size)
                if render_is_current:
                    display_path = display_icon_cache_path_for_file(raw_path, size)
                    try:
                        raw_stat = raw_path.stat()
                        display_stat = display_path.stat()
                        metadata = json.loads(icon_render_metadata_path(display_path).read_text(encoding="utf-8"))
                    except (OSError, ValueError, TypeError):
                        # A cleaner can remove a file after validation. Preserve
                        # other artwork, without recording a permanent miss.
                        render_records[render_key] = None
                        continue
                    render_records[render_key] = {
                        "dims": [metadata.get("output_width", size), metadata.get("output_height", size)],
                        "has_visual_detail": metadata.get("has_visual_detail", True),
                        "size": size,
                        "raw": raw_path.name,
                        "display": display_path.name,
                        "raw_stat": [raw_stat.st_mtime_ns, raw_stat.st_size],
                        "display_stat": [display_stat.st_mtime_ns, display_stat.st_size],
                    }
                elif expires_at := icon_render_miss_expires_at(raw_path, size):
                    render_misses[render_key] = expires_at
                else:
                    render_records[render_key] = None
            record = render_records.get(render_key)
            if record is None:
                if render_key in render_misses:
                    entry[f"{field}_unavailable"] = True
                    entry[f"{field}_unavailable_until"] = render_misses[render_key]
                continue
            entry[field] = dict(record)
            if field == "details":
                try:
                    compact = compact_icon_catalog_record(record)
                    if compact is not None:
                        entry["compact"] = compact
                except (OSError, ValueError):
                    pass  # Normal rendition remains usable; a future checkpoint retries.
        entries[item.key] = entry
    if len(entries) > ICON_CATALOG_MAX_ENTRIES:
        newest = sorted(
            entries.items(),
            key=lambda pair: float(pair[1].get("seen_at", 0.0) or 0.0),
            reverse=True,
        )[:ICON_CATALOG_MAX_ENTRIES]
        entries = dict(newest)
    return entries


def prune_stale_icon_cache_versions() -> int:
    """Remove obsolete generated icon formats without touching current cache data."""

    root = icon_cache_dir()
    if not root.exists():
        return 0
    current_prefixes = (
        "iconpack-" + DISPLAY_ICON_CACHE_PREFIX,
        APP_ICON_CACHE_PREFIX,
        DETAIL_ICON_CACHE_PREFIX,
        RAW_ICON_CACHE_PREFIX,
        DISPLAY_ICON_CACHE_PREFIX,
        PROVIDER_ICON_CACHE_PREFIX,
        VECTOR_ICON_CACHE_PREFIX,
    )
    families = (
        "iconpack-",
        "appicon-",
        "detailsicon-",
        "rawicon-",
        "displayicon-",
        "provider-alpha-dot-",
        "provider-minus-",
        "vectoricon-",
    )
    removed = 0
    for child in root.iterdir():
        name = child.name
        stale_version = name.startswith(families) and not name.startswith(current_prefixes)
        abandoned_temporary = False
        if name.startswith(".") and name.endswith((".tmp", ".raw.png")):
            try:
                abandoned_temporary = (
                    time.time() - child.stat().st_mtime >= 60 * 60
                )
            except OSError:
                continue
        if not child.is_file() or not (stale_version or abandoned_temporary):
            continue
        try:
            child.unlink()
            removed += 1
        except OSError:
            continue
    return removed


def source_versioned_raw_icon_cache_path(
    source: Path,
    target_size: int,
    *,
    small_shell_icon: bool,
) -> Path:
    """Address raw artwork by every stable input that can determine its pixels.

    Package identity and presentation palette deliberately do not participate.
    A direct PNG is copied byte-for-byte and can therefore back every display
    size. Other formats retain their effective extraction target because the
    selected embedded/Shell rendition can change with that request.
    """

    try:
        stat = source.stat()
        source_stamp = f"{stat.st_mtime_ns}:{stat.st_size}"
    except OSError:
        source_stamp = "missing"
    source_key = os.path.normcase(os.path.abspath(str(source)))
    if source.suffix.casefold() == ".png":
        extraction_variant = "native-png"
        filename_variant = "native"
    else:
        extraction_target = max(128, target_size) if small_shell_icon else target_size
        extraction_variant = "\n".join(
            (
                f"extract-{extraction_target}px",
                WINDOWS_ICON_EXTRACTION_REVISION,
                ICON_EXTRACTION_POLICY_REVISION,
            )
        )
        filename_variant = f"extract-{extraction_target}px"
        if source.suffix.casefold() in {".exe", ".dll"}:
            extraction_variant += "\npe-default-group-v1"
            if source.name.casefold() in _SHELL_PREFERRED_ICON_NAMES:
                extraction_variant += '\nshell-preferred-v1'
    identity = "\n".join((source_key, source_stamp, extraction_variant))
    digest = hashlib.sha256(identity.encode("utf-8", errors="replace")).hexdigest()[:32]
    return icon_cache_dir() / f"{RAW_ICON_CACHE_PREFIX}{filename_variant}-{digest}.png"


# ==================== Icon cache identity and artifacts ====================

def package_icon_cache_path_for_fields(
    provider: str,
    package_id: str,
    name: str,
    source: Path,
    size: int,
    _palette_mode: str,
) -> Path:
    """Return the package-independent raw path for one list-icon source version."""

    del provider, package_id, name, _palette_mode
    return source_versioned_raw_icon_cache_path(
        source,
        size,
        small_shell_icon=True,
    )


def details_icon_cache_path_for_fields(
    provider: str,
    package_id: str,
    name: str,
    source: Path,
    size: int,
) -> Path:
    """Return the package-independent raw path for one Details source version."""

    del provider, package_id, name
    return source_versioned_raw_icon_cache_path(
        source,
        size,
        small_shell_icon=False,
    )


def display_icon_cache_path_for_file(raw_path: Path, size: int) -> Path:
    try:
        stat = raw_path.stat()
        stamp = f"{stat.st_mtime_ns}:{stat.st_size}"
    except OSError:
        stamp = "missing"
    digest = hashlib.sha256(
        f"{raw_path}\n{stamp}\n{size}".encode("utf-8", errors="replace")
    ).hexdigest()[:32]
    return icon_cache_dir() / f"{DISPLAY_ICON_CACHE_PREFIX}{size}px-{digest}.png"


def icon_render_metadata_path(display_path: Path) -> Path:
    return display_path.with_suffix(".json")


def icon_render_miss_path(raw_path: Path, target_size: int) -> Path:
    # A failed former renderer must not suppress a newly simplified one.
    return raw_path.with_suffix(f".{DISPLAY_ICON_CACHE_PREFIX}{target_size}px.miss.json")


def write_icon_render_miss(raw_path: Path, target_size: int, reason: str) -> None:
    """Remember a source-versioned render miss so launches do not retry it continually."""

    destination = icon_render_miss_path(raw_path, target_size)
    destination.parent.mkdir(parents=True, exist_ok=True)
    temporary = destination.with_name(
        f".{destination.name}.{os.getpid()}.{threading.get_ident()}.tmp"
    )
    payload = {
        "schema": 1,
        "recorded_at": time.time(),
        "reason": reason[:500],
    }
    try:
        temporary.write_text(json.dumps(payload, ensure_ascii=False), encoding="utf-8")
        os.replace(temporary, destination)
    finally:
        with contextlib.suppress(OSError):
            temporary.unlink()


def icon_render_miss_expires_at(raw_path: Path, target_size: int) -> float:
    """Return a live source/renderer-specific failure deadline, or zero."""

    miss_path = icon_render_miss_path(raw_path, target_size)
    try:
        stat = miss_path.stat()
        if stat.st_size > 32_768:
            return 0.0
        age = time.time() - stat.st_mtime
    except OSError:
        return 0.0
    return stat.st_mtime + ICON_RENDER_MISS_TTL_SECONDS if 0 <= age <= ICON_RENDER_MISS_TTL_SECONDS else 0.0


def icon_render_miss_is_current(raw_path: Path, target_size: int) -> bool:
    return bool(icon_render_miss_expires_at(raw_path, target_size))


def write_icon_render_metadata(display_path: Path, metadata: Mapping[str, Any]) -> None:
    destination = icon_render_metadata_path(display_path)
    destination.parent.mkdir(parents=True, exist_ok=True)
    temporary = destination.with_name(
        f".{destination.name}.{os.getpid()}.{threading.get_ident()}.tmp"
    )
    try:
        temporary.write_text(
            json.dumps(dict(metadata), ensure_ascii=False, sort_keys=True),
            encoding="utf-8",
        )
        os.replace(temporary, destination)
    finally:
        with contextlib.suppress(OSError):
            temporary.unlink()


def icon_render_metadata_is_current(metadata: Any) -> bool:
    """Accept only the current resampler and valid recorded enlargement scales."""

    if not isinstance(metadata, dict) or metadata.get("schema") != 1:
        return False
    if metadata.get("resampling_policy") != ICON_RESAMPLING_POLICY:
        return False
    outline_revision = metadata.get("adaptive_outline_revision")
    if outline_revision != ADAPTIVE_OUTLINE_REVISION:
        # v2 only changes the decision for icons that v1 actually outlined:
        # alpha-weighting can withdraw a false outline, but cannot introduce a
        # new one. Preserve the overwhelmingly common unaffected cache entries.
        if not (
            outline_revision == "edge-dominance-v1"
            and not metadata.get("adaptive_outline_applied")
        ):
            return False
    if metadata.get("icon_extraction_policy_revision") != ICON_EXTRACTION_POLICY_REVISION:
        return False
    if type(metadata.get("upscaled")) is not bool:
        return False
    if not metadata["upscaled"]:
        return True
    try:
        scale_x = float(metadata["upscale_scale_x"])
        scale_y = float(metadata["upscale_scale_y"])
    except (KeyError, TypeError, ValueError):
        return False
    return (
        math.isfinite(scale_x) and math.isfinite(scale_y)
        and scale_x > 0 and scale_y > 0 and max(scale_x, scale_y) > 1.0
    )


def rendered_icon_cache_is_current(raw_path: Path, size: int) -> bool:
    """Cheaply validate one rendered icon without decoding its PNG pixels."""

    if not raw_path.exists():
        return False
    display_path = display_icon_cache_path_for_file(raw_path, size)
    metadata_path = icon_render_metadata_path(display_path)
    if not display_path.exists() or not metadata_path.exists():
        return False
    try:
        if metadata_path.stat().st_size > 32_768:
            return False
        metadata = json.loads(metadata_path.read_text(encoding="utf-8"))
    except (OSError, ValueError, TypeError):
        return False
    return icon_render_metadata_is_current(metadata)


def rgba_png_bytes(
    width: int,
    height: int,
    rgba_rows: Sequence[bytes],
    *,
    compression_level: int = 6,
) -> bytes:
    """Encode a simple 8-bit RGBA PNG entirely in memory."""

    if width <= 0 or height <= 0:
        raise ValueError("PNG dimensions must be positive")
    if len(rgba_rows) != height:
        raise ValueError("PNG row count does not match height")
    if any(len(row) != width * 4 for row in rgba_rows):
        raise ValueError("PNG row byte count does not match width")
    if not 0 <= compression_level <= 9:
        raise ValueError("PNG compression level must be between 0 and 9")
    # CPython's bytes join is marginally faster here than filling a pre-sized
    # bytearray row by row; each PNG scan line uses filter type 0.
    raw = b"".join(b"\x00" + row for row in rgba_rows)

    def chunk(kind: bytes, payload: bytes) -> bytes:
        return (
            struct.pack(">I", len(payload))
            + kind
            + payload
            + struct.pack(">I", zlib.crc32(kind + payload) & 0xFFFFFFFF)
        )

    return (
        b"\x89PNG\r\n\x1a\n"
        + chunk(b"IHDR", struct.pack(">IIBBBBB", width, height, 8, 6, 0, 0, 0))
        # Level 6 is roughly four times faster on our real icon cache while
        # increasing these tiny files by only about three percent.
        + chunk(b"IDAT", zlib.compress(raw, level=compression_level))
        + chunk(b"IEND", b"")
    )


def write_rgba_png(path: Path, width: int, height: int, rgba_rows: Sequence[bytes]) -> None:
    """Write an in-memory RGBA encoding atomically to a requested cache path."""

    write_png_bytes(path, rgba_png_bytes(width, height, rgba_rows))


def write_png_bytes(path: Path, payload: bytes) -> None:
    """Atomically publish an already-encoded PNG using the shared cache writer."""
    path.parent.mkdir(parents=True, exist_ok=True)
    temporary = path.with_name(f".{path.name}.{os.getpid()}.{threading.get_ident()}.tmp")
    try:
        temporary.write_bytes(payload)
        os.replace(temporary, path)
    finally:
        with contextlib.suppress(OSError):
            temporary.unlink()


def generated_app_icon_rows(size: int) -> list[bytes]:
    """Generate a simple square WinDevPilot icon: saturated blue-teal gradient."""

    rows: list[bytes] = []
    for y in range(size):
        row = bytearray()
        y_ratio = y / max(1, size - 1)
        for x in range(size):
            x_ratio = x / max(1, size - 1)
            diagonal = (x_ratio + y_ratio) * 0.5
            # Darker and more saturated than the header gradient, with a subtle
            # inner highlight so it reads as an app icon at small sizes.
            red = int(8 + 10 * (1.0 - diagonal))
            green = int(96 + 86 * x_ratio + 20 * (1.0 - y_ratio))
            blue = int(150 + 78 * (1.0 - x_ratio) + 20 * (1.0 - y_ratio))
            edge_distance = min(x, y, size - 1 - x, size - 1 - y) / max(1, size * 0.20)
            edge_shade = min(1.0, edge_distance)
            red = int(red * (0.72 + 0.28 * edge_shade))
            green = int(green * (0.72 + 0.28 * edge_shade))
            blue = int(blue * (0.72 + 0.28 * edge_shade))
            row.extend(
                (max(0, min(255, red)), max(0, min(255, green)), max(0, min(255, blue)), 255)
            )
        rows.append(bytes(row))
    return rows


VPL64_ENGINE_VERSION = "software16 v6"
VPL64_LANGUAGE_VERSION = "4.3"

# VPL64/4.3: [paint][/axis][width][.][!outline][^]geometry; 64-unit canvas.
# P polyline/polygon, B cubic, Q quadratic, C circle, E ellipse, G gear, R rounded box.
# ^ pairs geometry digits (1/64 units), except integer gear counts; ~q is quarter-width.
# Fine words also accept ~qq widths and paired axes. . rounds caps; ! adds an outline.
# Paint: palette or &RRGGBB[AA]; / axis or /* radial axis; %digits% positions stops.
# ;op adds an even-odd contour, |op adds nonzero winding; comma starts another shape.
# Omitted paint retains color/gradient axis; new paint resets the axis to diagonal.
# Color 0 erases all underlying layers with antialiased edges, unlike a fill-local hole.
# [A words ] draws/defines a local part; @A~ repeats mirrored across x=32.
# @A:tx,ty,scale,degrees[,mirror] or @A=a,b,c,d,tx,ty transforms a part.
# @A+ placement and *count provide bounded iteration; /style restyles a reference.
# [!A words ] defines silently; parts may use earlier parts within expansion budgets.
# Bounded drawing data only: no eval, fonts or external assets. See Workshop/V64_SPEC.md.
V64_DIGITS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-_"
V64_COLORS = dict(zip("0iwtrbcygvp", (
    0, 0xFF253141, 0xFFFFFFFF, 0xFFFFE9BE, 0xFFE17D54, 0xFF268ED6,
    0xFF42C7E7, 0xFFFFD85A, 0xFF37B992, 0xFF9B78EB, 0xFFF2A8AA,
)))
V64_COLORS.update(k=0xFF111111, h=0xFFFFF1DA, s=0xFFD1C2A7, e=0xFFF1D7C4, f=0xFFED5262)
V64_COLORS.update(d=0xFF342056, o=0xFF71398F, j=0xFF2686B6, l=0xFF65C5EB)
V64_COLORS.update(m=0xFF09657D, a=0xFF96C4E0, u=0xFF00A9DC)
V64_COLORS.update(n=0xFF65D7E7)  # User-reference Go gopher blue; transparent silhouette.
V64_COLORS.update(x=0xFF080B0B)  # Repeated near-black illustration ink.
V64_ICONS = {
    "wrench": "w1!Bh7d8aAXDSHSNVSQWLbHfAe8kDpIuOsNlRhWcaXfalapVsSuPvLtLrKoLmNkPjQfQcNcJdIfGhEiBh9h7 iCGm3 0CGm2",
"rust": "ryGWWSNG;CWWH r^QMGLWR8LWW0LWamLWd0N0f0OWf0RGf0VWZGWmbmaeeGeWf0fmgWfmgWgOgWh0deh0amh0Xmc8UmXGTeXGSWXGSWaOSWdWSWfmV0fmV0gOV0h0QGh0LWh0LWgOLWfmO0fmO0dWO0WGO0P0O0MwMGMwMGMDMGLW;QSWNGSWROSWVWTmVWV0VWaGVWaGROaGNGV0NGTmNGSWNG",
    "cargo": "rPW8tKtiWv9i9K w2PAKWXsK,WXWt,LEiRic",
    "cargo-binstall": "rGWWSNG;CWWH w~3!kPTJZJZWgWWjMWTW",
    "cargo-update": "rGWWSNG;CWWH 4BKUKJZGgP PZPiUiK 4BiYijTmMd PTdKYKi",
    "codex": "[A 7Bc9l6wEtP_ZyknnkyX_PtCw5o8c0T6IEFI3U1c9 ] @A/w5 w1!BJOIMMKNMPPRSTVUWUXTYRbPeNhMjIhJfKdNZPWNTLQJO,ZcWcWhZhchghjhmhmcjcgcccZc",
"opencode": "&3C3C3C&141414/000_~1!&454545R22yyC &090909RFDai0 &FFFFFF&BBBBBB/000_~1!&666666REAai0 &101010&55554B&18180D/000_~1!&777777RMJKS0",
    "corepack": "gcPW5uIukWx8k8I w3P9IWVtI,WVWw iPPHdHhLWSLL",
    "browser": "w!P79v9vp7p bP8AuAuL8L wCEF2,LF2 i!PVQVvdmjxouhjtj",
    "bun": "[!A &F4DAC7^BSW6WW050cWB0gWDWrWKWxWRWx0bWw0nWjWu0UWu0GWu050p020e000WW30PW7WKWDWEWMWAWSW6W ] @A:1.5,2,1,0/&000000 @A &FCF0DE^BSW6WW05Wc0B0g0DWp0JWvWQWvWZWuWl0iWrWU0rWFWrW50mW2Wc010V03WP080KWEWEWMWAWSW6W &CBBAA1^BR08WR0C0MWFWG0H0MWH0R0EWR08W,SW80UWCWRWHWO0JWT0IWVWD0SW80,U080Y0B0WWFWW0I0ZWEWXWA0U080,W08Wa0A0b0E0c0HWd0CWa09WW08W &FFB4CE^EJ0b0502W,g0b0502W &000000^CK0UW4G,eWUW4G w^CIXS01G,d0S01G &000000^BOWc0RWbWXWbWaWc0a0f0X0iWUWiWS0iWP0f0OWc0 &F06B78^BQ0eWSWcWX0cWZ0eWXWgWW0hWUWhWT0hWR0g0Q0eW",
    "llvm": "[A m~3!BIHDF9F5F2J1T2e3V5T8W9RCQETHRLWTYTUTRTPOPLOHOHLIJIH wB5F9EFGIHIHIIIIEG9F5F,2e0S6LIHAL2R2e a~1B8W9NENHOKQPSTS w~3BIHHLGPET aCIH1 ] @A~ a~2!BWhdckflkmphrcpgpknjjhebfWjPoIqFmKpRkWh [B u~2!BTZRYRcQeOdOaLZIYIbJdJaLbLcOgQiSdTbUaTZ wBKaIbIdKeJcLbKa,MbKcKeMfLdNcMb ] @B~ ~2!BSIYDcIZQXWWdakeropnksrhwapUkRYURWNZHSKQLONOMQKQJOKLKLINIQIQGSI wBVLYIYLWQTYUhZnetksnokuctXoRgSUVOWMWLVL aPQISEVDTGSI uPZIcJaK,ZMcNZO iPPJRIRJ ~2PUSWUYS,TXVZXX,UdWeXd,WiYjZi,Znbocn",
    "engagement": "ub/0W_WP5WSGSPxPxdSdSm",
    "chip": "b!PFFnFnnFn wPPPdPddPd [A b3PM7MF,W7WF,g7gF ] @A+WWWW4*3",
    "fonts": "w!PC6h6sHswCw i4PMlWKhl 3PQcdc,ImSm,bmlm",
    "node": "gcPW4vIvkWy7k7I w5PLiLKhihK",
    "vscode": "bcPl4yAyslyGY5h5LGU;PKWlClq cPl4yAysly",
    "visualstudio": "vPl5yAyslxMdAm3h3LAGMP;PTWlHll;PAPIWAd",
    "dotnet-native": "&A30CBD&512BD4/5WyWC5b3 PBKIKLbMbMKQKQeJeFMFeBe,UKhKhNYNYSgSgVYVYahaheUe,jKyKyNsNseoeoNjN",
    "terminal": "!P6CwCwq6q w4PFNOWFf g4PVfmf",
    "go": "&F3C4C8~2!x^BqYPqrJPqrrPds1OssDO8ruNCr2N4qYM_pNN3oGNEoWN-olOoozPfpZPmq7PqqYPq,s4msrElzq2lPomlJoLmNnsnFnHn-oPo8p8oeq1pDrNq4tIoAs4ms,QKyAQI-9TD-BTpyVU9xVURweV7voTwvjSkvTRbu_Qqv_QLx2QKyA &8AD2E5~2!x^BD0JvCOJzBqJWBmIvBiIHC9HkCmHfCwHeD3HfDBHiD9GpDBF_DIFEAqFK9iGm9aIW9SKNAhMEC_MODMMQDhMODzMLDkLRDYKaDPJnDIJrD9JuD0Jv x^BCmHfC9HkBiIHBmIvBrJWCOJzD0JvD9JuDIJrDPJnDIJ2DDIMDBHiD3HfCwHeCmHf &8AD2E5~2!x^Bdz5ke05fe45be95Yed58fK5Cfk5hg769g46rfd7FgC7rgl8ThG97hR8xhb8jhk8Siv6Ri34NgR3Sf22edN2hb-4FcA4NcM4VcX4dd14zdV5Ldz5k x^Bfk5hfK5Ced58e95Ye45be15fdz5keW6Bf36hfd7Fg46rg769fk5h &F3C4C8~2!x^BLsrvM3sLN7sNNqrvNSrINAqeMypzMCqSLZrELsrv &8AD2E5~2!x^BozPfolOooWN-oGNEndLMmpJvltJ6kzEtjDBchG97gl8TgC7rfd7Ff56jeY6Cdz5kdU5Kc_4ycX4dcM4VcA4Nb-4GYD1rT41AM95CHK81D-AdDIFEDBF_D9GpDBHiDDIMDIJ2DPJnDYKaDkLRDzMLEDNEEWOBEtPBG4SaIGVqJWXjKmZdLzd9M9geMIjGLzmvMypzNAqeNSrINqrvOTszPOtuQguZQzukRHutRbu_SkvTTwvjV7voa7wAfMtmhksFjwqslrprnHn-nsnFoLmNollJpEk2pbiVpqgZqSazq6UVoyPfoyPfozPfozPf w~2!x^EWe8k5B56,L3Ed5B56 x^CZS7w1d w^CaF800N x^CNmDY1d w^COZDe0N ~2!x^BUPInTRJETUJjSkKFS_KwTGLcTXMIUFO9WNMjVuLdVTKfV1JgUbIiUXIkUTIlUPIn,WzIJVtIlVXILUbIiV1JgVTKfVuLdWNMjYtM5X-KJXeJeXJI-WzIJ &F3C4C8~2!x^BfCUYeXUFdGU4c5UCb-UnbmVLbKVwcIWUdEWtd_X4ekXHfJXDfiWXg3Vtf-UvfCUY x~1.^BZeXOaPWuayWPbKVwbmVLb-Unc5UCcATkcBTHcBSp &F3C4C8~2!x^BXBFMWcF6W1F5VMFGVFFuUaGcTcH1SgHSRkHURAHBQZHdQBI4P-IjPcJzQbL9RgKmS9KbSUKQSkKFTUJjTRJEUPInUTIlUXIkUbIiVXILVtIlWzIJXAIEXPI7XgHzYgHOYOFtXBFM x^BTcH1UaGcVFFuVMFGVOF3VNEuVJEjU-D_TiDtSREQRBE-QQG1QkGlQqGxQzH5RAHBRkHUSgHSTcH1 ~1.^Bs4OcreOXq_OQqTOO,r_oprroOrQnZqanC,RlzcRbz8RRyHRoxH,foWJfPW6epVqeIVg",
    "uv": "vbP4GDGDeNeNGWGWm4m vPZGhGnctG_Grmjm",
    "cmake": "gcPW33wUk rPW3Yjzw gPUm3zzz",
    "ninja": "CWWS rP4PyPwe6e wPDSQUQZGY,cUpSmYcZ",
    "ripgrep": "gCRRK;CRRD 8Pffww w3.PHRNXaK",
}

# Reviewed replacements for generic Windows artwork; editable authoring source in Artwork/.
V64_ICONS.update({
    "deepseek-dsh": "&4D6BFFQQHVFYGUIXLdQhSiQiQcMeGfDgGgIjJlKlLnJqKsJtIvGtMrQmRlbfhiijimlfkdkckWpNn9k8W7MGILGQH wQCSLPTbYkbkXlShLbOgQjMiCfCS,XTaReYdaaYZXaVZUYUWUXT CYW1",
    "powertoys": "st/0_00~2!iR55ss7 iR99kb3 &F25022RCCAV0 &FFB900RMCAV0 &7FB900RWCAV0 &00A4EFRgCAV0 wRCm880,Sm880,im880",
    "ffmpeg": "&388E3C~R.^PBOBONGBOBONGBOc0c0BOqeBOBOqeQ0qeqeQ0qeememqeqeqe",
    "geekbench": "&73CDFB&1871CA/000_R44uuB &E9F7FF38~2P9GtG,9RtR,9ctc &AAF6FF&57C5E8/000_RCPAM2 &C5F58A&77C447/000_RRCAZ2 &AAF6FF&57C5E8/000_RgJAS2 &D9F6FF75~E!kR9bKF6,ZbKF6 k3BTfUdYdZf 3P6dBd,rdwd",
    "just": "&704032&B76B46/000_R6Aqm9 &FFBC7A&DC8E50/000_RA8ii8 &663D2CFF3.PW8W4 &FFDC9CFFCW43 &3E302ARFHYK6 [A &FFF0C6RKM693 ] @A+00I0 &704032FF3.PMiQmXe 2.Pdhih,dmim",
    "windows-compatibility": "&E5F6FF&92CDEE/000_R57km6 &188BDD&0861BC/000_RACaS3 &DCF6FFFF2PSDSd,BQjQ &7394ADFF2.PDkVk,DoQo &50D6B0&087C6C/000_~4!wBiWnasbxcyntuizXuSnTcYbdaiW w3.Pakgqqf",
    "sccache": "&6EA7EF&4152A5/000_B7I7ItItItItntntsiwVwIw7s7n7n7I7I &8DB7FF&6177D0/000_EVIO9 &B4CEFF80~5B8VIeiesV,8hIqiqsh &273465~4PGPBUGZ,PPUUPZ &FFE795&FFA836/000_~3!wPhRXigibyvclcrR",
})

# Artwork aliases only: these never establish installation or execution identity.
V64_ALIASES = {
    alias: style for style, aliases in {
        "rust": "rustlang.rustup rustup", "cargo-binstall": "cargo-binstall",
        "cargo-update": "cargo-update", "codex": "@openai/codex openai.codex",
        "opencode": "opencode-ai sst.opencodedesktop", "corepack": "corepack",
        "deepseek-dsh": "@deepseek-ai/dsh",
        "powertoys": "microsoft.powertoys.sparseapp",
        "browser": "browser-use", "bun": "oven-sh.bun bun arp\\user\\x64\\bun",
        "llvm": "llvm.llvm", "node": "openjs.nodejs openjs.nodejs.lts node",
        "vscode": "microsoft.visualstudiocode",
        "visualstudio": "microsoft.visualstudio.2022.buildtools",
        "terminal": "microsoft.windowsterminal",
        "go": "golang.go", "uv": "astral-sh.uv",
        "cmake": "kitware.cmake", "ninja": "ninja-build.ninja",
        "ripgrep": "burntsushi.ripgrep.msvc burntsushi.ripgrep.gnu",
    }.items() for alias in aliases.split()
}


_V64_PREFERRED_WINGET = {"golang.go": "go", "astral-sh.uv": "uv",
                         "microsoft.dotnet.native.runtime": "dotnet-native",
                         "gyan.ffmpeg": "ffmpeg", "casey.just": "just",
                         "mozilla.sccache": "sccache", "ninja-build.ninja": "ninja",
                         "burntsushi.ripgrep.msvc": "ripgrep", "burntsushi.ripgrep.gnu": "ripgrep"}


def preferred_vector_style(item: UpdateItem) -> str:
    """Narrow artwork-only replacements for known low-resolution package icons."""
    if item.provider == "winget":
        package_id = item.package_id.casefold()
        if style := _V64_PREFERRED_WINGET.get(package_id):
            return style
        if (item.name.casefold() == 'microsoft windows application compatibility fix database'
                and re.fullmatch(r'arp\\(?:machine|user)\\(?:x86|x64)\\\{[0-9a-f]{8}(?:-[0-9a-f]{4}){3}-[0-9a-f]{12}\}\.sdb', package_id)):
            return 'windows-compatibility'
    identity = item.package_id.casefold().removeprefix("msix\\").split("_", 1)[0]
    if item.provider not in {"winget", MICROSOFT_STORE_PROVIDER_KEY}:
        return ""
    if identity == "microsoft.services.store.engagement":
        return "engagement"
    return "dotnet-native" if re.fullmatch(
        r"microsoft\.net\.native\.(?:runtime|framework)(?:\.\d+)+", identity
    ) else ""


def fallback_vector_style(item: UpdateItem) -> str:
    if preferred := preferred_vector_style(item):
        return preferred
    if item.provider == "rustup":
        return "rust"
    identity = item.package_id.casefold()
    if identity.startswith("msix\\"):
        identity = identity[5:].split("_", 1)[0]
    return V64_ALIASES.get(identity) or {
        "oneapi level zero": "chip", "vs_coreeditorfonts": "fonts",
    }.get(item.name.casefold(), "wrench")


# V64/4 software renderer; keep pure parser/raster routines aligned with VectorWorkshop.
_V64_HEX = "&[0-9A-Fa-f]{6}(?:[0-9A-Fa-f]{2})?"  # RRGGBB or RRGGBBAA paint stop
_V64_STOP = re.compile(f"{_V64_HEX}|.")
_V64_PREFIX = (f"((?:[a-z0]|{_V64_HEX})*(?:%[A-Za-z0-9_-]+%)?)(?:/(?:\\*([A-Za-z0-9_-]{{3}})|([A-Za-z0-9_-]{{4}})))?"
                       "([1-9]|~[A-Za-z0-9_-])?(\\.?)"
                       f"(?:!((?:[a-z0]|{_V64_HEX})?))?")
_V64_STYLE = re.compile(_V64_PREFIX)
_V64_WORD = re.compile(_V64_PREFIX + r"(\^?[PBCGREQ])([A-Za-z0-9_,;|\-]+)")
_V64_FINE_PREFIX = (f"((?:[a-z0]|{_V64_HEX})*(?:%[A-Za-z0-9_-]+%)?)"
                   r"(?:/(?:\*([A-Za-z0-9_-]{3}|[A-Za-z0-9_-]{6})|([A-Za-z0-9_-]{4}|[A-Za-z0-9_-]{8})))?"
                   r"([1-9]|~[A-Za-z0-9_-]{1,2})?(\.?)"
                   f"(?:!((?:[a-z0]|{_V64_HEX})?))?")
_V64_FINE_WORD = re.compile(_V64_FINE_PREFIX + r"(\^[PBCGREQ])([A-Za-z0-9_,;|\-]+)")


def _v64_match_word(word: str):
    # Longer prefix fields are opt-in: coarse operator letters are also digits.
    return (_V64_FINE_WORD if "^" in word else _V64_WORD).fullmatch(word)


def _v64_digits(text: str, paired: bool = False) -> tuple:
    values = tuple(V64_DIGITS.index(c) for c in text)
    if paired:
        if len(values) % 2:
            raise ValueError("Fine values need digit pairs")
        return tuple(values[i]+values[i+1]/64 for i in range(0, len(values), 2))
    return values


def _v64_geometry_values(op: str, text: str, fine: bool) -> tuple:
    if fine and op == "G":
        if len(text) != 9:
            raise ValueError("Fine gear needs four pairs and one integer tooth count")
        return (*_v64_digits(text[:8], True), V64_DIGITS.index(text[8]))
    return _v64_digits(text, fine)
# Affine tuple (a,b,c,d,tx,ty): x'=a*x+c*y+tx; y'=b*x+d*y+ty.
_V64_IDENTITY = (1.0, 0.0, 0.0, 1.0, 0.0, 0.0)
_V64_FRINGE = bytes(0 if v in (0, 255) else 1 for v in range(256))


class _V64Gradient(tuple):
    """Immutable paint values with explicit stop positions; ordinary paints stay tuples."""
    def __new__(cls, colors, positions):
        result = super().__new__(cls, colors)
        object.__setattr__(result, "positions", tuple(positions))
        return result

    def __setattr__(self, name, value):
        raise AttributeError("Gradient is immutable")

    def __eq__(self, other):
        return isinstance(other, _V64Gradient) and tuple.__eq__(self, other) and self.positions == other.positions

    def __ne__(self, other):
        return not self == other

    def __hash__(self):
        return hash((tuple(self), self.positions))


def _v64_stop(token: str) -> int:
    """One paint stop: a palette key, or &RRGGBB[AA] packed into the same ARGB form."""
    if token.startswith("&"):
        value = int(token[1:], 16)
        if len(token) == 7:
            value = value << 8 | 0xFF
        red, green, blue, alpha = value >> 24 & 255, value >> 16 & 255, value >> 8 & 255, value & 255
        return alpha << 24 | red << 16 | green << 8 | blue
    try:
        return V64_COLORS[token]
    except KeyError:
        raise ValueError("Unknown V64 paint") from None


def _v64_radial(axis: tuple) -> bool:
    # A radial axis is (cx, cy, radius, "radial"); a linear one is four numbers.
    return isinstance(axis[3], str)


def _v64_style(fields, state):
    """Resolve paint/axis state and local stroke settings for words and restyled reuse."""
    paint, radial, axis, weight, caps, outline = fields
    if paint:
        stops, separator, positions = paint.partition("%")
        colors = tuple(_v64_stop(token) for token in _V64_STOP.findall(stops))
        if separator:
            positions = tuple(V64_DIGITS.index(c) for c in positions[:-1])
            if (len(colors) < 2 or len(positions) != len(colors) or positions[0] != 0
                    or positions[-1] != 63 or any(a >= b for a, b in zip(positions, positions[1:]))):
                raise ValueError("Gradient positions must increase from 0 to _, one per stop")
            colors = _V64Gradient(colors, positions)
        state[:] = [colors, (0, 0, 64, 64)]
    if radial:
        state[1] = _v64_digits(radial, len(radial) == 6) + ("radial",)
    elif axis:
        state[1] = _v64_digits(axis, len(axis) == 8)
    if len(state[0]) > 1 and (state[1][2] <= 0 if _v64_radial(state[1]) else state[1][:2] == state[1][2:]):
        raise ValueError("V64 gradient axis has zero length or radius")
    width = _v64_digits(weight[1:], len(weight) == 3)[0]/4 if weight and weight.startswith("~") else int(weight or 2)
    if width <= 0:
        raise ValueError("V64 stroke width must be positive and outline paint known")
    mode = "both" if outline is not None else "stroke" if weight else "fill"
    ink = (_v64_stop(outline or "i"),)
    return state[0], state[1], mode, width, bool(caps), ink


def _v64_words(words: Sequence[str], state: list[Any]) -> Iterator[tuple]:
    # Only paint and axis inherit; width/caps/outline are resolved anew per word.
    for word in words:
        match = _v64_match_word(word)
        if match is None:
            raise ValueError(f"Invalid V64 word: {word[:40]}")
        paint, radial, axis, weight, caps, outline, first, body = match.groups()
        fine, first = first.startswith("^"), first.lstrip("^")
        style = _v64_style((paint, radial, axis, weight, caps, outline), state)
        mode = style[2]
        for shape in body.split(","):  # A comma starts a new shape; ; adds an even-odd contour, | a nonzero one.
            contours, nonzero = [], "|" in shape
            for n, contour in enumerate(re.split("[;|]", shape)):
                op, contour = (first, contour) if n == 0 else (contour[:1], contour[1:])
                values = _v64_geometry_values(op, contour, fine)
                valid = op in "PBCGREQ" and (
                    (len(values) == 3 and values[2] > 0) if op == "C" else
                    (len(values) == 5 and 0 < values[3] <= values[2] and values[4] >= 3) if op == "G" else
                    (len(values) == 5 and 0 < min(values[2:4]) and 2*values[4] <= min(values[2:4])) if op == "R" else
                    (len(values) == 4 and min(values[2:]) > 0) if op == "E" else
                    (len(values) >= 8 and (len(values)-2) % 6 == 0) if op == "B" else
                    (len(values) >= 6 and (len(values)-2) % 4 == 0) if op == "Q" else
                    len(values) >= (4 if mode == "stroke" else 6) and len(values) % 2 == 0)
                if not valid:
                    raise ValueError(f"Invalid V64 {op or '?'} geometry")
                contours.append((op, values))
            # Command: colors, axis, mode, width, caps, ink, ((op, integer values), ...), nonzero fill.
            yield (*style, tuple(contours), nonzero)


def _v64_compose(outer: tuple, inner: tuple) -> tuple:
    """Compose placement matrices; identity shortcuts preserve legacy arithmetic."""
    if outer == _V64_IDENTITY:
        return inner
    if inner == _V64_IDENTITY:
        return outer
    a, b, c, d, x, y = outer
    e, f, g, h, u, v = inner
    result = (a*e+c*f, b*e+d*f, a*g+c*h, b*g+d*h, a*u+c*v+x, b*u+d*v+y)
    if not all(math.isfinite(value) and abs(value) <= 4096 for value in result):
        raise ValueError("V64 composed transform exceeds bounds")
    return result


def _v64_instances(word: str, parts: dict, state: list) -> Iterator[tuple]:
    """Expand a draw word or one reference; definitions are handled separately."""
    if not word.startswith("@"):
        for command in _v64_words((word,), state):
            yield command, _V64_IDENTITY
        return
    name, suffix = word[1:2], word[2:]
    suffix, separator, restyle = suffix.partition("/")
    if name not in parts:
        raise ValueError("Undefined V64 part")
    suffix, star, repeat = suffix.partition("*")
    repeat = V64_DIGITS.index(repeat) if star and len(repeat) == 1 and repeat in V64_DIGITS else 1 if not star else 0
    if repeat < 1:
        raise ValueError("V64 repeat count must be one base-64 digit from 1")
    matrix = _V64_IDENTITY
    if suffix.startswith("+"):
        # Place: pivot (px,py) lands on (qx,qy); optional 1/n turn (n = symmetry order) and scale s/16 about the pivot.
        digits = suffix[1:]
        if not 4 <= len(digits) <= 6 or any(c not in V64_DIGITS for c in digits):
            raise ValueError("V64 placement needs four to six base-64 digits")
        px, py, qx, qy = (V64_DIGITS.index(c) for c in digits[:4])
        turn = V64_DIGITS.index(digits[4]) if len(digits) > 4 else 0
        scale = V64_DIGITS.index(digits[5])/16 if len(digits) > 5 else 1.0
        if scale <= 0:
            raise ValueError("V64 placement scale must be positive")
        # The turn digit is the order of rotational symmetry: n means one n-th of a turn clockwise (0 = none).
        if turn in (0, 1, 2, 4):  # Half and quarter turns stay exact integers: placed art matches hand-expanded art bit for bit.
            cosine, sine = {0: (1, 0), 1: (1, 0), 2: (-1, 0), 4: (0, 1)}[turn]
        else:
            cosine, sine = math.cos(math.tau/turn), math.sin(math.tau/turn)
        cosine, sine = cosine*scale, sine*scale
        matrix = (cosine, sine, -sine, cosine, qx-cosine*px+sine*py, qy-sine*px-cosine*py)
    elif suffix == "~":
        matrix = (-1.0, 0.0, 0.0, 1.0, 64.0, 0.0)
    elif suffix.startswith("="):
        fields = tuple(float(value) for value in suffix[1:].split(","))
        if len(fields) != 6 or not all(math.isfinite(v) and abs(v) <= 4096 for v in fields):
            raise ValueError("Invalid V64 matrix values")
        matrix = fields
    elif suffix:
        if not suffix.startswith(":"):
            raise ValueError("Invalid V64 part transform")
        fields = tuple(float(value) for value in suffix[1:].split(","))
        if len(fields) not in (4, 5) or not all(math.isfinite(v) and abs(v) <= 4096 for v in fields):
            raise ValueError("Invalid V64 transform values")
        tx, ty, scale, angle = fields[:4]
        mirror = fields[4] if len(fields) == 5 else 1
        if not 0.0625 <= scale <= 16 or mirror not in (-1, 1):
            raise ValueError("Invalid V64 transform scale or reflection")
        cosine, sine = math.cos(math.radians(angle))*scale, math.sin(math.radians(angle))*scale
        matrix = (cosine*mirror, sine*mirror, -sine, cosine, tx, ty)
    style = None
    if separator:
        match = _V64_STYLE.fullmatch(restyle)
        if not restyle or match is None:
            raise ValueError("Invalid V64 reuse style")
        style = _v64_style(match.groups(), [(V64_COLORS["i"],), (0, 0, 64, 64)])
    step, placed = matrix, _V64_IDENTITY
    for _ in range(repeat):  # *n applies the same step n times: arrays, rings, spirals, progressions.
        placed = _v64_compose(step, placed)
        for command, local in parts[name]:
            if style is not None:
                if style[2] != "stroke" and any(op == "P" and len(values) < 6 for op, values in command[6]):
                    raise ValueError("Restyled polygon fill needs at least three vertices")
                command = (*style, command[6], command[7])
            yield command, _v64_compose(placed, local)


def _v64_commands(program: str) -> Iterator[tuple]:
    """Bounded earlier-part composition: [A draws; [!A defines without drawing."""
    if not program.strip() or len(program) > 16384:
        raise ValueError("Invalid V64 program length")
    words, parts, index, count, stored = program.split(), {}, 0, 0, 0
    state = [(V64_COLORS["i"],), (0, 0, 64, 64)]
    while index < len(words):
        word = words[index]
        if word.startswith("["):
            silent = word.startswith("[!")
            name = word[2:] if silent else word[1:]
            if len(name) != 1 or name not in "ABCDEFGHIJKLMNOPQRSTUVWXYZ" or name in parts:
                raise ValueError("Invalid or duplicate V64 part")
            try:
                end = words.index("]", index+1)
            except ValueError as exc:
                raise ValueError("Unclosed V64 part") from exc
            captured, local_state = [], [(V64_COLORS["i"],), (0, 0, 64, 64)]
            for member in words[index+1:end]:
                for instance in _v64_instances(member, parts, local_state):
                    stored += 1
                    if stored > 2048:
                        raise ValueError("V64 stored part shape limit exceeded")
                    captured.append(instance)
            if not captured:
                raise ValueError("Empty V64 part")
            parts[name], index = tuple(captured), end+1
            instances = () if silent else parts[name]
        else:
            instances = _v64_instances(word, parts, state)
            index += 1
        for instance in instances:
            count += 1
            if count > 2048:
                raise ValueError("V64 expanded shape limit exceeded")
            yield instance


def _v64_cubic(points: Sequence[tuple[float, float]], depth: int = 0) -> list[tuple[float, float]]:
    """Adaptive subdivision bounds control-point distance to the chord, including cusps."""
    start, a, b, end = points
    dx, dy = end[0]-start[0], end[1]-start[1]
    length2 = dx*dx+dy*dy
    def distance(point: tuple[float, float]) -> float:
        t = max(0.0, min(1.0, ((point[0]-start[0])*dx+(point[1]-start[1])*dy)/length2)) if length2 else 0.0
        return math.hypot(point[0]-start[0]-t*dx, point[1]-start[1]-t*dy)
    if depth >= 12 or max(distance(a), distance(b)) <= 0.125:
        return [end]
    def mid(p: tuple[float, float], q: tuple[float, float]) -> tuple[float, float]:
        return ((p[0]+q[0])/2, (p[1]+q[1])/2)
    ab, bc, cd = mid(start, a), mid(a, b), mid(b, end)
    left, right = mid(ab, bc), mid(bc, cd)
    center = mid(left, right)
    return _v64_cubic((start, ab, left, center), depth+1) + _v64_cubic((center, right, cd, end), depth+1)


def _v64_count(radius_px: float) -> int:
    """Segments per full turn keeping every chord's sagitta within 1/8 px."""
    return min(256, max(12, math.ceil(math.pi/math.acos(1-min(1.0, 0.125/max(radius_px, 0.125))))))


def _v64_arc(x: float, y: float, radius: float, count: int, start: float = 0.0, sweep: float = 1.0) -> list[tuple[float, float]]:
    """Arc measured in turns; disks, joins, caps and rounded boxes share this primitive."""
    steps = max(1, math.ceil(count*abs(sweep)))
    return [(x+radius*math.cos(math.tau*(start+sweep*n/steps)), y+radius*math.sin(math.tau*(start+sweep*n/steps)))
            for n in range(steps+(abs(sweep) < 1))]  # A full turn omits its repeated end point.


def v64_shapes(program: str, size: int) -> Iterator[tuple]:
    """Flatten bounded drawing instructions into pixel-space contours and paint."""
    if not isinstance(size, int) or not 8 <= size <= 1024:
        raise ValueError("Unsupported vector size")
    factor = size/64
    for (colors, axis, mode, width, caps, ink, contours, nonzero), matrix in _v64_commands(program):
        a, b, c, d, tx, ty = matrix
        def point(x: float, y: float) -> tuple[float, float]:
            return ((a*x+c*y+tx)*factor, (b*x+d*y+ty)*factor)
        scale = math.hypot(a, b)*factor
        similar = math.isclose(a*a+b*b, c*c+d*d, abs_tol=1e-12) and math.isclose(a*c+b*d, 0, abs_tol=1e-12)
        curve_scale = scale if similar else math.sqrt(a*a+b*b+c*c+d*d)*factor
        polygons, closed = [], []
        for op, values in contours:
            if op == "C":
                x, y = point(values[0], values[1])
                points = _v64_arc(x, y, values[2]*scale, _v64_count(values[2]*scale)) if similar else [
                    point(*p) for p in _v64_arc(values[0], values[1], values[2], _v64_count(values[2]*curve_scale))]
            elif op == "E":
                x, y, rx, ry = values
                # Bound angular chord error using the largest transformed radius.
                count = _v64_count(max(rx, ry)*curve_scale)
                points = [point(x+rx*math.cos(math.tau*n/count), y+ry*math.sin(math.tau*n/count))
                          for n in range(count)]
            elif op == "G":
                x, y, outer, inner, teeth = values
                points = [point(x+(outer if n%4 in (1, 2) else inner)*math.cos(n*math.tau/(teeth*4)),
                                y+(outer if n%4 in (1, 2) else inner)*math.sin(n*math.tau/(teeth*4)))
                          for n in range(teeth*4)]
            elif op == "R":
                x, y, w, h, r = values
                corners = ((x+w-r, y+r, -0.25), (x+w-r, y+h-r, 0.0), (x+r, y+h-r, 0.25), (x+r, y+r, 0.5))
                points = [point(*p) for cx, cy, first in corners for p in _v64_arc(cx, cy, r, _v64_count(r*curve_scale), first, 0.25)]
            else:
                points = [point(x, y) for x, y in zip(values[::2], values[1::2])]
                if op == "B":
                    curve = [points[0]]
                    for n in range(1, len(points), 3):
                        curve.extend(_v64_cubic((curve[-1], *points[n:n+3])))
                    points = curve
                elif op == "Q":
                    # Exact elevation to a cubic: c1 = P0 + 2/3(Q−P0), c2 = P1 + 2/3(Q−P1).
                    curve = [points[0]]
                    for n in range(1, len(points), 2):
                        (qx, qy), (ex, ey) = points[n:n+2]
                        sx, sy = curve[-1]
                        curve.extend(_v64_cubic(((sx, sy), (sx+2/3*(qx-sx), sy+2/3*(qy-sy)),
                                                 (ex+2/3*(qx-ex), ey+2/3*(qy-ey)), (ex, ey))))
                    points = curve
            closed.append(mode != "stroke" or op in "CGRE" or points[0] == points[-1])
            if len(points) > 1 and points[0] == points[-1]:
                points.pop()
            polygons.append(points)
        if _v64_radial(axis):
            gradient = (*point(axis[0], axis[1]), axis[2]*scale, "radial")
        else:
            gradient = (*point(*axis[:2]), *point(*axis[2:]))
        determinant = a*d-b*c
        if not similar and determinant:
            # Invert only the new general-affine path; legacy arithmetic stays unchanged.
            inverse = (d/determinant/factor, -b/determinant/factor,
                       -c/determinant/factor, a/determinant/factor)
            if not all(math.isfinite(value) and abs(value) <= 1e12 for value in inverse):
                raise ValueError('Affine transform is too close to singular for reliable rendering')
            if _v64_radial(axis):
                gradient = (*point(axis[0], axis[1]), axis[2], 'radial', inverse)
            else:
                dx, dy = axis[2]-axis[0], axis[3]-axis[1]
                norm = dx*dx+dy*dy
                if norm:
                    gx, gy = (inverse[0]*dx+inverse[1]*dy)/norm, (inverse[2]*dx+inverse[3]*dy)/norm
                    denominator = gx*gx+gy*gy
                    x, y = point(axis[0], axis[1])
                    gradient = (x, y, x+gx/denominator, y+gy/denominator)
            if mode != 'fill':
                # Stroke in local space, then transform the outline, including skewed joins.
                local = [[((d*(x/factor-tx)-c*(y/factor-ty))/determinant,
                           (-b*(x/factor-tx)+a*(y/factor-ty))/determinant) for x, y in polygon]
                         for polygon in polygons]
                local_width = max(1/scale, width) if scale > 0 else width
                pieces = [[point(*p) for p in piece] for polygon, ring in zip(local, closed)
                          for piece in _v64_stroke(polygon, local_width, ring, caps)]
                if mode == 'both':
                    yield colors, gradient, 'fill', 0, False, ink, polygons, tuple(closed), nonzero
                yield _v64_stroke_paint(ink if mode == 'both' else colors[:1], width*scale), gradient, 'fill', 0, False, ink, pieces, (True,)*len(pieces), True
                continue
        # Shape: first six command fields in pixel space, then polygons, closure flags, fill rule.
        yield colors, gradient, mode, width*scale, caps, ink, polygons, tuple(closed), nonzero


def _v64_coverage(size: int, polygons: Sequence[list], nonzero: bool) -> Iterator[tuple[int, int, float]]:
    """Exact horizontal coverage with eight vertical samples; even-odd fills, nonzero stroke unions.

    Edges enter from a y-sorted table as the sweep reaches them and every span is two
    difference-array updates plus its fractional end pixels; walking the row's events
    then yields (first pixel, count, coverage) runs of constant coverage. Sorting
    visits active edges and event boundaries, not every interior pixel."""
    table = sorted((min(y0, y1), max(y0, y1), (x0 if y0 < y1 else x1)-min(y0, y1)*(x1-x0)/(y1-y0),
                    (x1-x0)/(y1-y0), 1 if y1 > y0 else -1)
                   for polygon in polygons for (x0, y0), (x1, y1) in zip(polygon, polygon[1:]+polygon[:1]) if y0 != y1)
    if not table:
        return
    active, pending, parity = [], 0, not nonzero
    for row in range(max(0, math.floor(table[0][0])), min(size, math.ceil(max(e[1] for e in table)))):
        partial, delta = defaultdict(float), defaultdict(float)
        for sub in range(8):
            y = row+(sub+0.5)/8
            while pending < len(table) and table[pending][0] <= y:
                active.append(table[pending])
                pending += 1
            active = [edge for edge in active if edge[1] > y]
            crossings = [(intercept+y*slope, direction) for _, _, intercept, slope, direction in active]
            crossings.sort()
            winding = 0
            for n in range(len(crossings)-1):
                left, direction = crossings[n]
                winding += direction
                if not (winding & 1 if parity else winding):
                    continue
                right = crossings[n+1][0]
                if left < 0.0:
                    left = 0.0
                if right > size:
                    right = size
                if left >= right:
                    continue
                first, last = int(left), min(int(right), size-1)
                if first == last:
                    partial[first] += (right-left)/8
                else:
                    partial[first] += (first+1-left)/8
                    partial[last] += (right-last)/8
                    delta[first+1] += 0.125
                    delta[last] -= 0.125
        events, running, base = sorted(partial.keys() | delta.keys()), 0.0, row*size
        for x, following in zip(events, events[1:]+[size]):
            running += delta.get(x, 0.0)
            if (value := running+partial.get(x, 0.0)) > 1e-9:
                yield base+x, 1, value
            if running > 1e-9 and following > x+1:
                yield base+x+1, following-x-1, running


def _v64_stroke(points: list, width: float, closed: bool, caps: bool) -> list[list]:
    """Quads per segment, outer sectors at visible joins, disks for round caps; all oriented alike for a nonzero union."""
    half, polygons = width/2, []
    links = [(p, q) for p, q in zip(points, points[1:]+(points[:1] if closed else [])) if p != q]
    for (x0, y0), (x1, y1) in links:
        length = math.hypot(x1-x0, y1-y0)
        nx, ny = (y0-y1)/length*half, (x1-x0)/length*half
        polygons.append([(x0-nx, y0-ny), (x1-nx, y1-ny), (x1+nx, y1+ny), (x0+nx, y0+ny)])
    count = _v64_count(half)
    for (p, q), (_, r) in zip(links, links[1:]+(links[:1] if closed else [])):
        heading = math.atan2(q[1]-p[1], q[0]-p[0])/math.tau
        turn = (math.atan2(r[1]-q[1], r[0]-q[0])/math.tau-heading+0.5) % 1-0.5
        if half*math.sin(abs(turn)*math.pi) >= 0.0625:  # Bound omitted join notches to 1/16 px.
            arc = _v64_arc(*q, half, count, heading-math.copysign(0.25, turn), turn)
            polygons.append([q]+(arc if turn > 0 else arc[::-1]))
    if caps and links and not closed:
        polygons += [_v64_arc(*end, half, count) for end in (links[0][0], links[-1][1])]
    return polygons


@functools.lru_cache(maxsize=64)
def _v64_ramp(colors: tuple[int, ...]) -> tuple[array.array, ...]:
    """Shared, read-only premultiplied ramps; retain 16-bit interpolation precision."""
    stops = [(color >> 16 & 255, color >> 8 & 255, color & 255, color >> 24) for color in colors]
    span, ramp = len(stops)-1, []
    positions = getattr(colors, "positions", ())
    for step in range(256 if span else 1):
        t = step/255*span
        lo = min(int(t), max(span-1, 0))
        if positions:
            position = step/255*63
            lo = next((n for n in range(span) if position <= positions[n+1]), span-1)
            t = lo+(position-positions[lo])/(positions[lo+1]-positions[lo])
        red, green, blue, opacity = (round(257*(a+(b-a)*(t-lo)))
                                   for a, b in zip(stops[lo], stops[min(lo+1, span)]))
        ramp.append(array.array('H', ((red*opacity+32767)//65535,
                                     (green*opacity+32767)//65535,
                                     (blue*opacity+32767)//65535, opacity)))
    return tuple(ramp)


def _v64_paint(pixels: array.array, size: int, runs: Iterable[tuple[int, int, float]], colors: Sequence[int], axis: Sequence[float]) -> None:
    """Bulk-copy opaque spans; blend at 16 bits; paint 0 erases with antialiased edges."""
    # Only the single paint (0,) erases; transparent gradient stops still source-over.
    ramp = _v64_ramp(colors if isinstance(colors, _V64Gradient) else tuple(colors))
    span, erase = len(colors)-1, tuple(colors) == (0,)
    opaque = all(color >> 24 == 255 for color in colors)
    radial = _v64_radial(axis)
    inverse = axis[4] if len(axis) == 5 else None
    radial_distance = math.hypot
    if inverse:
        a, b, c, d = inverse
        def radial_distance(x, y):
            return math.hypot(a*x+c*y, b*x+d*y)
    if radial:
        x0, y0, radius = axis[0], axis[1], axis[2]
    else:
        x0, y0, x1, y1 = axis
        dx, dy = x1-x0, y1-y0
        norm = dx*dx+dy*dy
    for start, count, value in runs:
        if value >= 1 and (opaque or erase) and not span:
            pixels[start*4:(start+count)*4] = ramp[0]*count
        elif value >= 1 and opaque:
            x, y = start%size+0.5, start//size+0.5
            if radial:
                stops = (max(0, min(255, round(radial_distance(x+n-x0, y-y0)/radius*255))) if radius > 0 else 255
                         for n in range(count))
            elif norm:
                t, step = ((x-x0)*dx+(y-y0)*dy)/norm*255, dx/norm*255
                stops = (max(0, min(255, round(t+n*step))) for n in range(count))
            else:
                stops = (255 for n in range(count))  # Degenerate axis: last stop, as in common formats.
            pixels[start*4:(start+count)*4] = array.array('H', itertools.chain.from_iterable(ramp[s] for s in stops))
        else:
            weight = round(65535*min(1.0, value))
            for index in range(start, start+count):
                if not span:
                    t = 0.0
                elif radial:
                    t = radial_distance(index%size+0.5-x0, index//size+0.5-y0)/radius if radius > 0 else 1.0
                else:
                    t = ((index%size+0.5-x0)*dx+(index//size+0.5-y0)*dy)/norm if norm else 1.0
                red, green, blue, opacity = ramp[max(0, min(255, round(t*255)))]
                alpha, offset = weight if erase else (weight*opacity+32767)//65535, index*4
                keep = 65535-alpha
                pixels[offset] = (red*weight+pixels[offset]*keep+32767)//65535
                pixels[offset+1] = (green*weight+pixels[offset+1]*keep+32767)//65535
                pixels[offset+2] = (blue*weight+pixels[offset+2]*keep+32767)//65535
                pixels[offset+3] = (0 if erase else alpha)+(pixels[offset+3]*keep+32767)//65535


def _v64_stroke_paint(paint: Sequence[int], width: float) -> tuple:
    """Keep subpixel strokes continuous while preserving their intended lightness."""
    if width >= 1 or tuple(paint) == (0,):
        return tuple(paint)  # Erasure is a coverage operation, not transparent ink.
    # Zero is the explicit eraser sentinel; fully faded black must remain transparent paint.
    return tuple(((c & 0xFFFFFF) | (round((c >> 24)*max(0, width)) << 24)) or 1 for c in paint)


def _vector_software_rows(size: int, shapes: Sequence[tuple], *, coverage=None) -> list[bytes]:
    """Pure-Python rendering; no optional backend import or dispatch."""
    # Workshop may memoize geometry; painting and pixel conversion stay shared.
    coverage = _v64_coverage if coverage is None else coverage
    pixels = array.array('H', [0])*(size*size*4)
    for colors, axis, mode, width, caps, ink, polygons, closed, nonzero in shapes:
        if mode != 'stroke':
            _v64_paint(pixels, size, coverage(size, polygons, nonzero), colors, axis)
        if mode != 'fill':
            # Minimum one-pixel geometry; thinner requests reduce ink opacity.
            pieces = [piece for polygon, ring in zip(polygons, closed)
                      for piece in _v64_stroke(polygon, max(1.0, width), ring, caps)]
            _v64_paint(pixels, size, coverage(size, pieces, True), _v64_stroke_paint(ink if mode == 'both' else colors[:1], width), axis)
    # Take each uint16's high byte; unpremultiply only the partial-alpha pixels below.
    packed = bytearray(pixels.tobytes()[1 if sys.byteorder == 'little' else 0::2])
    fringe, index = packed[3::4].translate(_V64_FRINGE), 0
    while (index := fringe.find(1, index)) >= 0:
        offset, alpha = index*4, pixels[index*4+3]
        half = alpha//2
        packed[offset] = min(255, (pixels[offset]*255+half)//alpha)
        packed[offset+1] = min(255, (pixels[offset+1]*255+half)//alpha)
        packed[offset+2] = min(255, (pixels[offset+2]*255+half)//alpha)
        packed[offset+3] = (alpha*255+32767)//65535
        index += 1
    return [bytes(packed[y*size*4:(y+1)*size*4]) for y in range(size)]


_VECTOR_FLIGHT_LOCK = threading.Lock()
_VECTOR_FLIGHTS: dict[tuple[str, int], list[Any]] = {}


def vector_icon_png(style: str, size: int) -> bytes:
    """Share identical in-flight renders; unrelated sizes/styles never wait on each other."""
    if style not in V64_ICONS or not isinstance(size, int) or not 8 <= size <= 1024:
        raise ValueError("Unknown vector icon or unsupported size")
    key = (style, size)
    with _VECTOR_FLIGHT_LOCK:
        flight = _VECTOR_FLIGHTS.get(key)
        if flight is None:
            flight = _VECTOR_FLIGHTS[key] = [threading.Lock(), 0]
        flight[1] += 1
    try:
        with flight[0]:
            return _vector_icon_png(style, size)
    finally:
        with _VECTOR_FLIGHT_LOCK:
            flight[1] -= 1
            if not flight[1]:
                del _VECTOR_FLIGHTS[key]


@functools.lru_cache(maxsize=96)
def _vector_icon_png(style: str, size: int) -> bytes:
    """Render generated illustrations entirely in software, once per cached key."""
    if style not in V64_ICONS:
        raise ValueError("Unknown vector icon")
    shapes = list(v64_shapes(V64_ICONS[style], size))
    rows = _vector_software_rows(size, shapes)
    return rgba_png_bytes(size, size, rows, compression_level=1)


def vector_bitmap_cache_path(style: str, size: int) -> Path:
    if style not in V64_ICONS or not 8 <= size <= 1024:
        raise ValueError("Unknown vector icon or unsupported size")
    # Raster policy C changes thin strokes independently of language precision.
    identity = ("V64/software16-v6-opacity", V64_ICONS[style], sorted(V64_COLORS.items()), size)
    digest = hashlib.sha256(repr(identity).encode("ascii")).hexdigest()[:24]
    return icon_cache_dir() / f"{VECTOR_ICON_CACHE_PREFIX}{style}-{size}px-{digest}.png"


def vector_icon_self_test() -> None:
    """Validate trusted drawings and analytic areas through the software renderer."""
    for package_id, expected in (
        ("@deepseek-ai/dsh", "deepseek-dsh"),
        ("MSIX\\Microsoft.PowerToys.SparseApp_0.101.2362.0_neutral__8wekyb3d8bbwe", "powertoys"),
        ("MSIX\\Microsoft.PowerToys.SparseApp_9.9.9.0_x64__8wekyb3d8bbwe", "powertoys"),
        ("@deepseek-ai/dsh-extra", "wrench"),
        ("MSIX\\Microsoft.PowerToys.SparseAppExtra_1_neutral__example", "wrench"),
    ):
        item = UpdateItem("npm" if package_id.startswith("@") else "winget",
                          "Artwork fixture", package_id, "1", "2")
        assert fallback_vector_style(item) == expected
    for compact, expanded in (
        ('[A i7CWW8 ] @A/w5', 'i7CWW8 w5CWW8'),
        ('&FFFFFFFF2Q00W0_0', 'w2P00_0'),
        ('wP88u8uu8u|POOeOeeOe', 'wP88u8uu8u'),
    ):
        assert _vector_software_rows(24, list(v64_shapes(compact, 24))) == _vector_software_rows(24, list(v64_shapes(expanded, 24)))
    assert list(v64_shapes('[A wr/*WWKEWWK8 ] @A=1,0,0.3,1,0,0', 24))
    for style, program in V64_ICONS.items():
        rows = _vector_software_rows(24, list(v64_shapes(program, 24)))
        assert len(rows) == 24 and all(len(row) == 96 for row in rows), style
        assert any(any(row[3::4]) for row in rows), style
    rows = _vector_software_rows(64, list(v64_shapes("wP88u8uu8u;POOeOeeOe", 64)))
    assert rows[32][131] == 0 and sum(sum(row[3::4]) for row in rows) == 255*2048
    for name, program, expected in (
        ("flat line", "w4P8WuW", 192),
        ("round caps", "w4.P8WuW", 192+4*math.pi),
        ("ring", "w4CWWK", 160*math.pi),
        ("right-angle join", "w8PWWgWgg", 144+4*math.pi),
        ("erased disk", "wP88u8uu8u 0CWW8", 2304-64*math.pi),
        ("mirrored rounded box", "[A wR44KK4 ] @A~", 2*(400-(4-math.pi)*16)),
    ):
        rows = _vector_software_rows(64, list(v64_shapes(program, 64)))
        area = sum(sum(row[3::4]) for row in rows)/255
        assert abs(area-expected) < 0.01*expected, (name, area, expected)


def icon_rainbow_sort_key(png: bytes) -> tuple[int, float, float]:
    """Visible color strength chooses hue; dark tints and gray noise stay neutral."""
    decoded = read_png_rgba(png)
    if decoded is None:
        return (2, 0.0, 0.0)
    width, height, rows = decoded
    histogram = [0.0]*36
    visible = colored = luminance = 0.0
    stride = max(1, math.ceil(max(width, height)/32))
    for y in range(stride//2, height, stride):
        row = rows[y]
        for x in range(stride//2, width, stride):
            red, green, blue, alpha = row[x*4:x*4+4]
            if alpha < 32:
                continue  # Transparent padding and faint antialiased fringes are not colors.
            visible += alpha
            luminance += alpha*(2126*red+7152*green+722*blue)
            hue, saturation, value = colorsys.rgb_to_hsv(red/255, green/255, blue/255)
            if saturation >= 0.12 and value >= 0.10 and max(red, green, blue)-min(red, green, blue) >= 12:
                colored += alpha
                # Saturation alone exaggerates near-black tints. Brightness squared
                # lets a clear colored mark outweigh a larger dark background.
                histogram[round(hue*36)%36] += alpha*saturation*value*value
    if not visible:
        return (2, 0.0, 0.0)
    lightness = luminance/(visible*2550000)
    if colored < visible*0.15 or sum(histogram) < visible*0.06:
        return (1, lightness, 0.0)
    families = [0.0]*6
    for index, strength in enumerate(histogram):
        families[round(index/6)%6] += strength
    total_strength = sum(histogram)
    # Balanced multicolor art can have a slightly smaller third family after
    # gradient sampling. Keep the stricter cutoff for a majority-color icon.
    family_share = 0.11 if max(families) <= total_strength*0.50 else 0.12
    substantial = [n for n, strength in enumerate(families) if strength >= total_strength*family_share]
    if len(substantial) >= 3:
        gaps = [b-a for a,b in zip(substantial, substantial[1:]+[substantial[0]+6])]
        if max(gaps) <= 3:
            return (0, 1.0, lightness)  # Multicolor, after violet and before neutral artwork.
    # Neighbor bins keep a gradient from losing to a narrower minor accent.
    dominant = max(range(36), key=lambda n: (
        histogram[(n-1)%36]+histogram[n]+histogram[(n+1)%36], histogram[n], -n
    ))
    # Resolve the wraparound red family before widening the gradient neighborhood.
    if dominant >= 33 or dominant <= 1:
        return (0, 0.0, lightness)
    # A broad orange/green/etc. gradient should beat a narrower bright accent.
    dominant = max(range(36), key=lambda n: (
        sum(histogram[(n+d)%36] for d in (-2,-1,0,1,2)), histogram[n], -n
    ))
    # A tiny accent can shift the winning window away from its actual color.
    # An overwhelming single-bin majority is also its weighted median; center
    # only those cases, leaving mixed hues, gradients and rainbow policy intact.
    for offset in (-2, -1, 0, 1, 2):
        candidate = (dominant + offset) % 36
        if histogram[candidate] >= total_strength * .90:
            dominant = candidate
            break
    return (0, 0.0 if dominant >= 33 else dominant/36, lightness)


def load_icon_color_cache() -> dict[str, tuple[int, float, float]]:
    """Worker-only, content-addressed colors; revision in filename permits reclassification."""
    try:
        with (icon_cache_dir() / "appicon-colors-v7.json").open("rb") as stream:
            data = json.loads(stream.read(2_000_001))
        if not isinstance(data, dict) or len(data) > 10000:
            return {}
        return {key: tuple(value) for key, value in data.items()
                if isinstance(key, str) and re.fullmatch(r"[0-9a-f]{64}", key)
                and isinstance(value, list) and len(value) == 3
                and value[0] in (0, 1) and all(type(v) in (int, float)
                    and math.isfinite(v) and 0 <= v <= 1 for v in value)}
    except (OSError, ValueError, TypeError):
        return {}


@dataclasses.dataclass(slots=True)
class VectorBitmap:
    path: Path
    png: bytes
    persisted: bool = False

    def persist(self) -> None:
        """Worker-only; callers share the catalog/graphics-cleanup write lock."""
        if not self.persisted:
            self.path.parent.mkdir(parents=True, exist_ok=True)
            attributes = self.path.parent.lstat()
            if not stat.S_ISDIR(attributes.st_mode) or getattr(attributes, "st_file_attributes", 0) & 0x400:
                raise OSError("Vector icon cache is not a regular directory")
            write_png_bytes(self.path, self.png)
            self.persisted = True


def cached_vector_bitmap(style: str, size: int) -> VectorBitmap:
    """Read a shared bitmap once; generate on a miss, but never write on Tk's thread."""
    return _load_vector_bitmap(style, size, vector_bitmap_cache_path(style, size))


@functools.lru_cache(maxsize=128)
def _load_vector_bitmap(style: str, size: int, path: Path) -> VectorBitmap:
    with contextlib.suppress(OSError):
        attributes = path.lstat()
        if stat.S_ISREG(attributes.st_mode) and not getattr(attributes, "st_file_attributes", 0) & 0x400:
            with path.open("rb") as stream:
                png = stream.read(size*size*4+4097)
            if valid_vector_bitmap_png(png, size):
                return VectorBitmap(path, png, True)
    return VectorBitmap(path, vector_icon_png(style, size))


def valid_vector_bitmap_png(png: bytes, size: int) -> bool:
    """Validate our fixed three-chunk, filter-zero RGBA encoding without copying pixel rows."""
    header = b"IHDR" + struct.pack(">IIBBBBB", size, size, 8, 6, 0, 0, 0)
    if not 57 <= len(png) <= size*size*4+4096 or png[:33] != (
        b"\x89PNG\r\n\x1a\n\x00\x00\x00\r" + header + struct.pack(">I", zlib.crc32(header))
    ):
        return False
    length = int.from_bytes(png[33:37], "big")
    if len(png) != length+57 or png[37:41] != b"IDAT" or png[-12:] != b"\0\0\0\0IEND\xaeB`\x82":
        return False
    if zlib.crc32(png[37:41+length]) != int.from_bytes(png[41+length:45+length], "big"):
        return False
    inflater = zlib.decompressobj()
    expected = size*(size*4+1)
    try:
        raw = inflater.decompress(png[41:41+length], expected+1)
    except zlib.error:
        return False
    return (len(raw) == expected and inflater.eof and not inflater.unconsumed_tail
            and not inflater.unused_data and not any(raw[::size*4+1]))


def vector_gallery_records(style: str, sizes: Sequence[int]) -> list[tuple[dict[str, Any], bytes]]:
    """Use the ordinary Lineup bundle/showcase path, retaining explicit provenance."""
    records = []
    for size in sorted(set(sizes)):
        bitmap = cached_vector_bitmap(style, size)
        records.append(({
            "filename": bitmap.path.name, "width": size, "height": size,
            "sources": [str(bitmap.path)], "retrievals": [f"WinDevPilot vector — {style}"],
            "generated_vector": True, "checkerboard": True, "represented_sizes": [[size, size]],
        }, bitmap.png))
    return records


def _png_paeth(left: int, up: int, upper_left: int) -> int:
    estimate = left + up - upper_left
    distance_left = abs(estimate - left)
    distance_up = abs(estimate - up)
    distance_upper_left = abs(estimate - upper_left)
    if distance_left <= distance_up and distance_left <= distance_upper_left:
        return left
    if distance_up <= distance_upper_left:
        return up
    return upper_left


@functools.lru_cache(maxsize=32)
def _png_up_filter_masks(width: int) -> tuple[int, int]:
    return int.from_bytes(b"\x7f" * width, "big"), int.from_bytes(b"\x80" * width, "big")


def _png_up_filter_in_place(current: bytearray, previous: bytearray) -> None:
    """Apply PNG's bytewise Up filter using carry-isolated big-int lanes."""

    low_mask, high_mask = _png_up_filter_masks(len(current))
    current_value = int.from_bytes(current, "big")
    previous_value = int.from_bytes(previous, "big")
    current[:] = (
        ((current_value & low_mask) + (previous_value & low_mask))
        ^ ((current_value ^ previous_value) & high_mask)
    ).to_bytes(len(current), "big")


def _png_sub_filter_in_place(current: bytearray, bpp: int) -> None:
    """Reconstruct each PNG channel's prefix sum, exactly modulo 256.

    Doubling the shift combines 1, 2, 4, ... preceding pixels per pass. Splitting
    off each byte's high bit prevents carries crossing channel boundaries. Small
    rows avoid big-int setup; unusually wide rows retain the scalar memory bound
    instead of adding large masks to the shared 32-entry cache.
    """
    width = len(current)
    if bpp <= 0:
        raise ValueError("PNG bytes per pixel must be positive")
    if width <= bpp:
        return
    if width < 32 or width > 16 * 1024:
        for index in range(bpp, width):
            current[index] = (current[index] + current[index - bpp]) & 0xFF
        return
    low_mask, high_mask = _png_up_filter_masks(width)
    value = int.from_bytes(current, "little")
    shift = bpp * 8
    while shift < width * 8:
        shifted = value << shift
        value = ((value & low_mask) + (shifted & low_mask)) ^ ((value ^ shifted) & high_mask)
        shift *= 2
    current[:] = value.to_bytes(width, "little")


def read_png_rgba(path: Path | bytes) -> tuple[int, int, list[bytes]] | None:
    """Read common 8-bit PNG variants into RGBA rows.

    This intentionally supports only formats we expect from Windows Shell/GDI+
    and AppX logos: truecolor, truecolor+alpha, palette, and grayscale.
    Unsupported PNG variants fall back to Tk's normal loader.
    """

    if isinstance(path, bytes):
        data = path
    else:
        try:
            data = path.read_bytes()
        except OSError:
            return None
    if not data.startswith(b"\x89PNG\r\n\x1a\n"):
        return None
    offset = 8
    width = height = bit_depth = color_type = 0
    idat_chunks: list[bytes] = []
    palette: list[tuple[int, int, int]] = []
    palette_alpha: dict[int, int] = {}
    while offset + 8 <= len(data):
        length = int.from_bytes(data[offset : offset + 4], "big")
        if offset + 12 + length > len(data):
            return None
        kind = data[offset + 4 : offset + 8]
        payload = data[offset + 8 : offset + 8 + length]
        offset += 12 + length
        if kind == b"IHDR":
            if len(payload) != 13:
                return None
            width = int.from_bytes(payload[0:4], "big")
            height = int.from_bytes(payload[4:8], "big")
            bit_depth = payload[8]
            color_type = payload[9]
            if payload[10:13] != b"\x00\x00\x00" or bit_depth != 8:
                return None
        elif kind == b"PLTE":
            palette = [
                (payload[index], payload[index + 1], payload[index + 2])
                for index in range(0, len(payload) - 2, 3)
            ]
        elif kind == b"tRNS":
            palette_alpha = {index: alpha for index, alpha in enumerate(payload)}
        elif kind == b"IDAT":
            idat_chunks.append(payload)
        elif kind == b"IEND":
            break
    if width <= 0 or height <= 0 or width * height > MAX_ICON_DECODE_PIXELS or not idat_chunks:
        return None
    channels_by_type = {0: 1, 2: 3, 3: 1, 4: 2, 6: 4}
    channels = channels_by_type.get(color_type)
    if channels is None:
        return None
    stride = width * channels
    expected_inflated_size = height * (stride + 1)
    try:
        decompressor = zlib.decompressobj()
        inflated = decompressor.decompress(b"".join(idat_chunks), expected_inflated_size + 1)
    except zlib.error:
        return None
    if (
        len(inflated) != expected_inflated_size
        or not decompressor.eof
        or decompressor.unconsumed_tail
    ):
        return None
    rows: list[bytes] = []
    previous = bytearray(stride)
    cursor = 0
    palette_tables: tuple[bytes, bytes, bytes, bytes] | None = None
    if color_type == 3:
        palette_tables = (
            bytes(palette[index][0] if index < len(palette) else 0 for index in range(256)),
            bytes(palette[index][1] if index < len(palette) else 0 for index in range(256)),
            bytes(palette[index][2] if index < len(palette) else 0 for index in range(256)),
            bytes(palette_alpha.get(index, 255) for index in range(256)),
        )
    for _y in range(height):
        if cursor >= len(inflated):
            return None
        filter_type = inflated[cursor]
        cursor += 1
        current = bytearray(inflated[cursor : cursor + stride])
        cursor += stride
        if len(current) != stride:
            return None
        if filter_type == 2:
            _png_up_filter_in_place(current, previous)
        elif filter_type == 1:
            _png_sub_filter_in_place(current, channels)
        elif filter_type != 0:
            for index in range(stride):
                left = current[index - channels] if index >= channels else 0
                up = previous[index]
                upper_left = previous[index - channels] if index >= channels else 0
                if filter_type == 3:
                    current[index] = (current[index] + ((left + up) // 2)) & 0xFF
                elif filter_type == 4:
                    current[index] = (current[index] + _png_paeth(left, up, upper_left)) & 0xFF
                else:
                    return None
        rgba = bytearray(width * 4)
        if color_type == 6:
            rgba[:] = current
        elif color_type == 2:
            rgba[0::4] = current[0::3]
            rgba[1::4] = current[1::3]
            rgba[2::4] = current[2::3]
            rgba[3::4] = b"\xff" * width
        elif color_type == 3:
            assert palette_tables is not None
            rgba[0::4] = current.translate(palette_tables[0])
            rgba[1::4] = current.translate(palette_tables[1])
            rgba[2::4] = current.translate(palette_tables[2])
            rgba[3::4] = current.translate(palette_tables[3])
        elif color_type == 0:
            rgba[0::4] = current
            rgba[1::4] = current
            rgba[2::4] = current
            rgba[3::4] = b"\xff" * width
        elif color_type == 4:
            gray = current[0::2]
            rgba[0::4] = gray
            rgba[1::4] = gray
            rgba[2::4] = gray
            rgba[3::4] = current[1::2]
        rows.append(bytes(rgba))
        previous = current
    return width, height, rows


def rgba_rows_are_conservative_near_duplicate(
    left_rows: Sequence[bytes],
    right_rows: Sequence[bytes],
    width: int,
    height: int,
) -> bool:
    """Recognize API renditions that differ only by negligible RGB rounding.

    Windows' icon APIs can encode the same frame with a few one-level RGB
    differences.  Requiring a byte-identical alpha plane and comparing
    premultiplied RGB keeps this deliberately narrower than perceptual image
    matching: different masks, frames, sizes, and meaningful colors survive.
    """

    row_size = width * 4
    if (
        width <= 0
        or height <= 0
        or len(left_rows) != height
        or len(right_rows) != height
        or any(len(row) != row_size for row in (*left_rows, *right_rows))
    ):
        return False
    squared_error = 0.0
    absolute_error = 0.0
    for left, right in zip(left_rows, right_rows, strict=True):
        if left[3::4] != right[3::4]:
            return False
        for offset in range(0, row_size, 4):
            alpha_scale = left[offset + 3] / 255.0
            for channel in range(3):
                error = (left[offset + channel] - right[offset + channel]) * alpha_scale
                squared_error += error * error
                absolute_error += abs(error)
    sample_count = width * height * 3
    return (
        math.sqrt(squared_error / sample_count) <= 0.5
        and absolute_error / sample_count <= 0.15
    )


def icon_gallery_visual_signature(
    rows: Sequence[bytes], width: int, height: int
) -> tuple[float, bytes] | None:
    """Normalize visible artwork for conservative cross-size gallery deduplication."""

    bbox = _visible_rgba_bbox(rows, width, height, alpha_threshold=8)
    if bbox is None:
        return None
    visible_width, visible_height, cropped = _crop_rgba(rows, width, bbox)
    normalized = _scale_rgba_bilinear(
        cropped,
        visible_width,
        visible_height,
        32,
        32,
    )
    return visible_width / visible_height, b"".join(_premultiply_rgba_rows(normalized))


def icon_gallery_signatures_match(
    left: tuple[float, bytes], right: tuple[float, bytes]
) -> bool:
    """Match only near-identical normalized art, never merely similar logos."""

    left_aspect, left_pixels = left
    right_aspect, right_pixels = right
    if (
        not left_pixels
        or len(left_pixels) != len(right_pixels)
        or abs(math.log(left_aspect / right_aspect)) > 0.08
    ):
        return False
    squared_error = 0
    absolute_error = 0
    for left_value, right_value in zip(left_pixels, right_pixels, strict=True):
        error = left_value - right_value
        squared_error += error * error
        absolute_error += abs(error)
    samples = len(left_pixels)
    return (
        math.sqrt(squared_error / samples) <= 5.0
        and absolute_error / samples <= 1.5
    )


# ==================== PNG decoding and image processing ====================

@dataclasses.dataclass(frozen=True, slots=True)
class PngHeader:
    width: int
    height: int
    bit_depth: int
    color_type: int

    @property
    def dimensions(self) -> tuple[int, int]:
        return self.width, self.height

    @property
    def has_explicit_alpha(self) -> bool:
        return self.color_type in {4, 6}


def png_header_fast(path: Path | bytes) -> PngHeader | None:
    """Read and validate the bounded IHDR fields used by cache decisions."""

    if isinstance(path, bytes):
        header = path[:26]
    else:
        try:
            with path.open("rb") as stream:
                header = stream.read(26)
        except OSError:
            return None
    if len(header) < 24 or not header.startswith(PNG_SIGNATURE) or header[12:16] != b"IHDR":
        return None
    width = int.from_bytes(header[16:20], "big")
    height = int.from_bytes(header[20:24], "big")
    if width <= 0 or height <= 0 or width * height > MAX_ICON_DECODE_PIXELS:
        return None
    bit_depth = header[24] if len(header) >= 25 else -1
    color_type = header[25] if len(header) >= 26 else -1
    return PngHeader(width, height, bit_depth, color_type)


def png_dimensions_fast(path: Path | bytes) -> tuple[int, int] | None:
    """Read PNG dimensions from IHDR without decoding image pixels."""

    header = png_header_fast(path)
    return header.dimensions if header is not None else None


def _rgba_rows_opaque(rows: Sequence[bytes]) -> bool:
    """Return True when every pixel is fully opaque (the common exe-icon case).

    Uses strided bytes views, so the scan runs at C speed; when true, callers
    can skip premultiply/unpremultiply round-trips entirely.
    """

    return all(min(row[3::4]) == 255 for row in rows) if rows else True


# bytes.translate tables that classify alpha values at C speed.
_PARTIAL_ALPHA_TRANSLATE = bytes(1 if 0 < value < 255 else 0 for value in range(256))
_BINARY_ALPHA_TRANSLATE = bytes(
    0 if value <= 8 else (2 if value >= 247 else 1) for value in range(256)
)
_ZERO_ALPHA_TRANSLATE = bytes(255 if value == 0 else 0 for value in range(256))


def _rgba_has_dirty_transparent_rgb(rows: Sequence[bytes]) -> bool:
    """True when any fully transparent pixel carries a nonzero RGB payload.

    Plane slices, a translate mask, and big-integer bitwise ops keep the check
    at C speed even on megapixel source artwork, so callers can defer the
    actual sanitation pass until the image has been cropped down.
    """

    if not rows:
        return False
    alphas = b"".join(row[3::4] for row in rows)
    if b"\x00" not in alphas:
        return False
    reds = b"".join(row[0::4] for row in rows)
    greens = b"".join(row[1::4] for row in rows)
    blues = b"".join(row[2::4] for row in rows)
    rgb = int.from_bytes(reds, "big") | int.from_bytes(greens, "big") | int.from_bytes(blues, "big")
    return bool(rgb & int.from_bytes(alphas.translate(_ZERO_ALPHA_TRANSLATE), "big"))


def _rgba_alpha_profile(rows: Sequence[bytes]) -> tuple[bool, bool]:
    """Return (uses_transparency, uses_partial_alpha) without a Python pixel loop.

    Strided row slices plus bytes.translate keep the scan at C speed, which
    matters on the large source artwork that precedes a 20px or 144px render.
    """

    if not rows:
        return False, False
    alphas = b"".join(row[3::4] for row in rows)
    if not alphas:
        return False, False
    uses_transparency = min(alphas) < 255
    uses_partial_alpha = b"\x01" in alphas.translate(_PARTIAL_ALPHA_TRANSLATE)
    return uses_transparency, uses_partial_alpha


def icon_gallery_needs_checkerboard(rows: Sequence[bytes]) -> bool:
    """Reveal every genuinely non-opaque gallery asset, even at one pixel."""

    uses_transparency, _uses_partial_alpha = _rgba_alpha_profile(rows)
    return uses_transparency


def _scale_rgba_bilinear(
    rows: Sequence[bytes],
    source_width: int,
    source_height: int,
    target_width: int,
    target_height: int,
) -> list[bytes]:
    """Bilinear resample with clamped pixel-center taps and premultiplied alpha."""

    inv_x = source_width / max(1, target_width)
    inv_y = source_height / max(1, target_height)
    x_taps: list[tuple[int, int, float, float]] = []
    for x in range(target_width):
        source_x = (x + 0.5) * inv_x - 0.5
        x0 = math.floor(source_x)
        weight_x = source_x - x0
        x_taps.append(
            (
                min(source_width - 1, max(0, x0)) * 4,
                min(source_width - 1, max(0, x0 + 1)) * 4,
                1.0 - weight_x,
                weight_x,
            )
        )
    y_taps: list[tuple[int, int, float, float]] = []
    for y in range(target_height):
        source_y = (y + 0.5) * inv_y - 0.5
        y0 = math.floor(source_y)
        weight_y = source_y - y0
        y_taps.append(
            (
                min(source_height - 1, max(0, y0)),
                min(source_height - 1, max(0, y0 + 1)),
                1.0 - weight_y,
                weight_y,
            )
        )
    opaque = _rgba_rows_opaque(rows)
    if opaque:
        source = rows
    else:
        # Premultiply only the rows the taps below can actually read. Large
        # downscales sample a small minority of source rows, which turns a
        # full-image per-pixel loop into a handful of row conversions while
        # producing byte-identical samples.
        sampled_indices = {
            row_index
            for ya, yb, _weight_y0, _weight_y in y_taps
            for row_index in (ya, yb)
        }
        ordered = sorted(sampled_indices)
        source = list(rows)
        for row_index, premultiplied in zip(
            ordered, _premultiply_rgba_rows([rows[i] for i in ordered])
        ):
            source[row_index] = premultiplied
    output: list[bytes] = []
    for ya, yb, weight_y0, weight_y in y_taps:
        row_a = source[ya]
        row_b = source[yb]
        out = bytearray(target_width * 4)
        for x, (ia, ib, weight_x0, weight_x) in enumerate(x_taps):
            w00 = weight_x0 * weight_y0
            w01 = weight_x * weight_y0
            w10 = weight_x0 * weight_y
            w11 = weight_x * weight_y
            offset = x * 4
            value0 = (
                row_a[ia] * w00
                + row_a[ib] * w01
                + row_b[ia] * w10
                + row_b[ib] * w11
            )
            value1 = (
                row_a[ia + 1] * w00
                + row_a[ib + 1] * w01
                + row_b[ia + 1] * w10
                + row_b[ib + 1] * w11
            )
            value2 = (
                row_a[ia + 2] * w00
                + row_a[ib + 2] * w01
                + row_b[ia + 2] * w10
                + row_b[ib + 2] * w11
            )
            value3 = (
                row_a[ia + 3] * w00
                + row_a[ib + 3] * w01
                + row_b[ia + 3] * w10
                + row_b[ib + 3] * w11
            )
            out[offset] = max(0, min(255, int(value0 + 0.5)))
            out[offset + 1] = max(0, min(255, int(value1 + 0.5)))
            out[offset + 2] = max(0, min(255, int(value2 + 0.5)))
            out[offset + 3] = max(0, min(255, int(value3 + 0.5)))
        output.append(bytes(out))
    return output if opaque else _unpremultiply_rgba_rows(output)


def _premultiply_rgba_rows(rows: Sequence[bytes]) -> list[bytes]:
    output: list[bytes] = []
    alpha_tables = ALPHA_PREMULTIPLY_TABLES
    for row in rows:
        alpha_plane = row[3::4]
        if alpha_plane and min(alpha_plane) == 255:
            output.append(row)
            continue
        if alpha_plane and not alpha_plane.strip(b"\0"):
            output.append(bytes(len(row)))
            continue
        premultiplied = bytearray(row)
        for index in range(0, len(row), 4):
            alpha = row[index + 3]
            if alpha >= 255:
                continue
            elif alpha <= 0:
                premultiplied[index] = 0
                premultiplied[index + 1] = 0
                premultiplied[index + 2] = 0
            else:
                table = alpha_tables[alpha]
                premultiplied[index] = table[row[index]]
                premultiplied[index + 1] = table[row[index + 1]]
                premultiplied[index + 2] = table[row[index + 2]]
        output.append(bytes(premultiplied))
    return output


def _unpremultiply_rgba_rows(rows: Sequence[bytes]) -> list[bytes]:
    output: list[bytes] = []
    for row in rows:
        alpha_plane = row[3::4]
        if alpha_plane and min(alpha_plane) == 255:
            output.append(row)
            continue
        straight = bytearray()
        for index in range(0, len(row), 4):
            red, green, blue, alpha = row[index : index + 4]
            if alpha >= 255:
                straight.extend((red, green, blue, alpha))
            elif alpha <= 0:
                straight.extend((0, 0, 0, 0))
            else:
                straight.extend(
                    (
                        min(255, (red * 255 + alpha // 2) // alpha),
                        min(255, (green * 255 + alpha // 2) // alpha),
                        min(255, (blue * 255 + alpha // 2) // alpha),
                        alpha,
                    )
                )
        output.append(bytes(straight))
    return output


def _sanitize_fully_transparent_rgb(rows: Sequence[bytes]) -> list[bytes]:
    """Zero meaningless RGB payload only where alpha is exactly zero.

    Partially visible pixels—including very faint ones—are preserved byte for
    byte. This is deterministic sanitation, not alpha denoising or artwork
    reconstruction.
    """

    cleaned: list[bytes] = []
    for source_row in rows:
        # Rows without any fully transparent pixel need no inspection; this
        # C-speed check skips the per-pixel loop for entire opaque spans.
        if b"\x00" not in source_row[3::4]:
            cleaned.append(source_row)
            continue
        row: bytearray | None = None
        for index in range(0, len(source_row), 4):
            if source_row[index + 3] != 0:
                continue
            if source_row[index] or source_row[index + 1] or source_row[index + 2]:
                if row is None:
                    row = bytearray(source_row)
                row[index : index + 3] = b"\x00\x00\x00"
        cleaned.append(bytes(row) if row is not None else source_row)
    return cleaned


def _has_mostly_binary_alpha(rows: Sequence[bytes], width: int, height: int) -> bool:
    # One translate plus three C-speed byte counts replace the former
    # per-pixel Python classification loop; thresholds are unchanged.
    classified = b"".join(row[3 : width * 4 : 4] for row in rows).translate(_BINARY_ALPHA_TRANSLATE)
    transparent = classified.count(b"\x00")
    partial = classified.count(b"\x01")
    opaque = classified.count(b"\x02")
    total = transparent + opaque + partial
    return total > 0 and partial / total <= 0.02 and transparent > 0 and opaque > 0


def _smooth_binary_alpha_edges(rows: Sequence[bytes], width: int, height: int) -> list[bytes]:
    """Soften crude 0/255 cutout edges after icon upscaling.

    This creates a small antialias ramp by deriving edge alpha from neighboring
    opaque coverage and copying nearby opaque color into newly translucent edge
    pixels. Icons that already have real alpha antialiasing are left alone.
    """

    if width <= 2 or height <= 2 or not _has_mostly_binary_alpha(rows, width, height):
        return list(rows)
    # Only pixels within one pixel of opaque coverage can change. Use the
    # exact kernel threshold, not the perceptual artwork crop (which can omit
    # faint pixels). Preserve every original byte outside this neighborhood.
    bounds = _visible_rgba_bbox(rows, width, height, alpha_threshold=246)
    if bounds is None:
        return list(rows)
    output = [bytearray(row) for row in rows]
    for y in range(max(0, bounds[1] - 1), min(height, bounds[3] + 2)):
        for x in range(max(0, bounds[0] - 1), min(width, bounds[2] + 2)):
            index = x * 4
            alpha = rows[y][index + 3]
            opaque_neighbors: list[tuple[int, int, int]] = []
            coverage = 0
            samples = 0
            for yy in range(max(0, y - 1), min(height, y + 2)):
                for xx in range(max(0, x - 1), min(width, x + 2)):
                    if yy == y and xx == x:
                        continue
                    samples += 1
                    neighbor_index = xx * 4
                    neighbor_alpha = rows[yy][neighbor_index + 3]
                    if neighbor_alpha >= 247:
                        coverage += 1
                        opaque_neighbors.append(
                            (
                                rows[yy][neighbor_index],
                                rows[yy][neighbor_index + 1],
                                rows[yy][neighbor_index + 2],
                            )
                        )
            if not samples or coverage == 0 or coverage == samples:
                continue
            if alpha <= 8:
                # Add a faint outside edge only when there is enough support to
                # avoid growing random specks.
                if coverage < 2:
                    continue
                red = sum(pixel[0] for pixel in opaque_neighbors) // len(opaque_neighbors)
                green = sum(pixel[1] for pixel in opaque_neighbors) // len(opaque_neighbors)
                blue = sum(pixel[2] for pixel in opaque_neighbors) // len(opaque_neighbors)
                output[y][index : index + 4] = bytes((red, green, blue, min(96, coverage * 24)))
            elif alpha >= 247:
                # Feather hard inside corners without eating solid edges.
                if coverage <= samples // 2:
                    output[y][index + 3] = 184
                elif coverage < samples:
                    output[y][index + 3] = 224
    return [bytes(row) for row in output]


def _resize_rgba_for_icon(
    rows: Sequence[bytes],
    source_width: int,
    source_height: int,
    target_width: int,
    target_height: int,
) -> list[bytes]:
    """Use alpha-correct bilinear resizing for every non-identity scale."""

    if source_width <= 0 or source_height <= 0 or target_width <= 0 or target_height <= 0:
        return []
    if source_width == target_width and source_height == target_height:
        return [bytes(row) for row in rows]
    return _scale_rgba_bilinear(rows, source_width, source_height, target_width, target_height)


@functools.lru_cache(maxsize=32)
def _alpha_threshold_mask_table(alpha_threshold: int) -> bytes:
    return bytes(1 if alpha > alpha_threshold else 0 for alpha in range(256))


def _visible_rgba_bbox(
    rows: Sequence[bytes], width: int, height: int, *, alpha_threshold: int = 24
) -> tuple[int, int, int, int] | None:
    min_x, min_y, max_x, max_y = width, height, -1, -1
    threshold_table = _alpha_threshold_mask_table(alpha_threshold)
    for y in range(height):
        visible_mask = rows[y][3::4].translate(threshold_table)
        row_min = visible_mask.find(b"\x01")
        if row_min < 0:
            continue
        min_y = min(min_y, y)
        max_y = max(max_y, y)
        min_x = min(min_x, row_min)
        max_x = max(max_x, visible_mask.rfind(b"\x01"))
    if max_x < min_x or max_y < min_y:
        return None
    return min_x, min_y, max_x, max_y


def _display_artwork_rgba_bbox(
    rows: Sequence[bytes],
    width: int,
    height: int,
) -> tuple[int, int, int, int] | None:
    """Bound the perceptually substantial art inside a translucent canvas.

    Some shell/installer icons place a small opaque mark inside a full-canvas
    low-alpha frame or haze. Treating that haze as the artwork prevents the
    recognizable mark from ever being enlarged. We retain the ordinary alpha
    bounds unless a high-alpha core is compact *and* the low-alpha bounds span
    almost the whole canvas, then keep a modest halo around that core.
    """

    ordinary = _visible_rgba_bbox(rows, width, height, alpha_threshold=24)
    if ordinary is None:
        return None
    core = _visible_rgba_bbox(rows, width, height, alpha_threshold=96)
    if core is None:
        return ordinary
    ordinary_width = ordinary[2] - ordinary[0] + 1
    ordinary_height = ordinary[3] - ordinary[1] + 1
    core_width = core[2] - core[0] + 1
    core_height = core[3] - core[1] + 1
    ordinary_spans_canvas = (
        ordinary_width >= width * 0.90 and ordinary_height >= height * 0.90
    )
    compact_core = core_width <= width * 0.72 and core_height <= height * 0.72
    if not (ordinary_spans_canvas and compact_core):
        return ordinary
    margin = max(2, min(8, round(max(core_width, core_height) * 0.10)))
    return (
        max(0, core[0] - margin),
        max(0, core[1] - margin),
        min(width - 1, core[2] + margin),
        min(height - 1, core[3] + margin),
    )


def _crop_rgba(
    rows: Sequence[bytes], width: int, bbox: tuple[int, int, int, int]
) -> tuple[int, int, list[bytes]]:
    min_x, min_y, max_x, max_y = bbox
    crop_width = max_x - min_x + 1
    crop_height = max_y - min_y + 1
    cropped = [bytes(rows[y][min_x * 4 : (max_x + 1) * 4]) for y in range(min_y, max_y + 1)]
    return crop_width, crop_height, cropped


def _pad_rgba(
    rows: Sequence[bytes],
    width: int,
    height: int,
    padding: int,
) -> tuple[int, int, list[bytes]]:
    if padding <= 0:
        return width, height, list(rows)
    padded_width = width + padding * 2
    empty = bytes(padded_width * 4)
    output = [empty for _ in range(padding)]
    for row in rows:
        output.append(bytes(padding * 4) + row + bytes(padding * 4))
    output.extend(empty for _ in range(padding))
    return padded_width, height + padding * 2, output


def _visible_art_touches_edge(width: int, height: int, bbox: tuple[int, int, int, int]) -> bool:
    min_x, min_y, max_x, max_y = bbox
    return min_x <= 0 or min_y <= 0 or max_x >= width - 1 or max_y >= height - 1


def _pad_source_if_edge_touched(
    rows: Sequence[bytes],
    width: int,
    height: int,
    bbox: tuple[int, int, int, int],
    padding: int,
) -> tuple[int, int, list[bytes], tuple[int, int, int, int]]:
    if padding <= 0 or not _visible_art_touches_edge(width, height, bbox):
        return width, height, list(rows), bbox
    padded_width, padded_height, padded_rows = _pad_rgba(rows, width, height, padding)
    min_x, min_y, max_x, max_y = bbox
    return (
        padded_width,
        padded_height,
        padded_rows,
        (min_x + padding, min_y + padding, max_x + padding, max_y + padding),
    )


def render_icon_png_for_display(
    source: Path,
    destination: Path,
    target_size: int,
    *,
    fit_art_at_scale: float | None = None,
    render_metadata: dict[str, Any] | None = None,
) -> bool:
    decoded = read_png_rgba(source)
    if decoded is None:
        return False
    return _render_icon_png_for_display_decoded(
        decoded,
        destination,
        target_size,
        fit_art_at_scale=fit_art_at_scale,
        render_metadata=render_metadata,
    )


@dataclasses.dataclass(frozen=True, slots=True)
class IconGalleryMemoryBundle:
    payload: bytes
    item_count: int
    shared_items: tuple[tuple[Mapping[str, Any], bytes], ...] = ()

    @property
    def raw_size(self) -> int:
        return len(self.payload)

    def unpack(self) -> list[tuple[dict[str, Any], bytes]]:
        raw = self.payload
        if len(raw) < 4:
            raise ValueError("icon gallery payload is truncated")
        metadata_size = struct.unpack("<I", raw[:4])[0]
        metadata_end = 4 + metadata_size
        if metadata_end > len(raw):
            raise ValueError("icon gallery metadata is truncated")
        metadata = json.loads(raw[4:metadata_end].decode("utf-8"))
        records = metadata.get("items") if isinstance(metadata, Mapping) else None
        if not isinstance(records, list) or len(records) > MAX_ICON_GALLERY_RESULTS:
            raise ValueError("icon gallery metadata is invalid")
        images = raw[metadata_end:]
        unpacked: list[tuple[dict[str, Any], bytes]] = []
        for value in records:
            if not isinstance(value, Mapping):
                raise ValueError("icon gallery item is invalid")
            record = dict(value)
            offset = record.pop("png_offset", None)
            size = record.pop("png_size", None)
            if type(offset) is not int or type(size) is not int:
                raise ValueError("icon gallery offsets and sizes must be integers")
            if offset < 0 or size <= 0 or offset + size > len(images):
                raise ValueError("icon gallery image span is invalid")
            unpacked.append((record, images[offset : offset + size]))
        # Generated PNGs remain shared objects; only their small metadata is copied.
        unpacked.extend((dict(record), png) for record, png in self.shared_items)
        if len(unpacked) != self.item_count or len(unpacked) > MAX_ICON_GALLERY_RESULTS:
            raise ValueError("icon gallery item count changed")
        return unpacked


def pack_icon_gallery_memory(
    directory: Path, payload: Mapping[str, Any]
) -> IconGalleryMemoryBundle:
    """Ingest helper PNGs into one raw session-memory bundle."""

    values = payload.get("items", [])
    if not isinstance(values, list) or len(values) > MAX_ICON_GALLERY_RESULTS:
        raise ValueError("icon gallery helper returned invalid items")
    in_memory_items: list[tuple[Mapping[str, Any], bytes]] = []
    total_bytes = 0
    for value in values:
        if not isinstance(value, Mapping):
            raise ValueError("icon gallery helper returned an invalid item")
        record = dict(value)
        helper_path = record.pop("path", None)
        if not isinstance(helper_path, str):
            raise ValueError("icon gallery helper omitted an image name")
        filename = Path(helper_path).name
        if not filename:
            raise ValueError("icon gallery helper omitted an image name")
        # Limit the read itself, including aggregate retention. A size check
        # followed by read_bytes() would still allow a growing file to exceed it.
        limit = min(MAX_ICON_GALLERY_IMAGE_BYTES, MAX_ICON_GALLERY_BUNDLE_BYTES - total_bytes)
        try:
            with (directory / filename).open("rb") as stream:
                image = stream.read(limit + 1)
        except OSError as exc:
            raise ValueError(f"icon gallery helper image could not be read: {exc}") from exc
        if not image or len(image) > limit:
            raise ValueError("icon gallery helper image exceeds the remaining memory limit or is empty")
        total_bytes += len(image)
        record["filename"] = filename
        in_memory_items.append((record, image))
    return pack_icon_gallery_memory_items(in_memory_items)


def pack_icon_gallery_memory_items(
    values: Sequence[tuple[Mapping[str, Any], bytes]],
    *,
    shared_items: Sequence[tuple[Mapping[str, Any], bytes]] = (),
) -> IconGalleryMemoryBundle:
    """Pack owned PNGs, retaining generated artwork by reference instead of per-app copies."""

    if len(values) + len(shared_items) > MAX_ICON_GALLERY_RESULTS:
        raise ValueError("icon gallery helper returned too many items")
    records: list[dict[str, Any]] = []
    image_parts: list[bytes] = []
    offset = 0
    for value, image in values:
        record = dict(value)
        if not image or len(image) > MAX_ICON_GALLERY_IMAGE_BYTES:
            raise ValueError("icon gallery helper returned an invalid PNG")
        record["png_offset"] = offset
        record["png_size"] = len(image)
        offset += len(image)
        if offset > MAX_ICON_GALLERY_BUNDLE_BYTES:
            raise ValueError("icon gallery images exceed the memory bundle limit")
        records.append(record)
        image_parts.append(image)
    metadata = json.dumps(
        {"items": records}, ensure_ascii=False, separators=(",", ":")
    ).encode("utf-8")
    if any(not image or len(image) > MAX_ICON_GALLERY_IMAGE_BYTES for _record, image in shared_items):
        raise ValueError("icon gallery shared PNG is invalid")
    if 4 + len(metadata) + offset + sum(len(image) for _record, image in shared_items) > MAX_ICON_GALLERY_BUNDLE_BYTES:
        raise ValueError("icon gallery metadata exceeds the memory bundle limit")
    raw = struct.pack("<I", len(metadata)) + metadata + b"".join(image_parts)
    return IconGalleryMemoryBundle(
        payload=raw,
        item_count=len(records) + len(shared_items),
        shared_items=tuple(shared_items),
    )


def serialize_icon_gallery_bundle(bundle: IconGalleryMemoryBundle) -> bytes:
    if bundle.shared_items:
        # IPC is the explicit materialization boundary; in-process galleries share bytes.
        bundle = pack_icon_gallery_memory_items(bundle.unpack())
    return (
        struct.pack(
            "<8sQI",
            ICON_GALLERY_WIRE_MAGIC,
            bundle.raw_size,
            bundle.item_count,
        )
        + bundle.payload
    )


def deserialize_icon_gallery_bundle(payload: bytes) -> IconGalleryMemoryBundle:
    header_size = struct.calcsize("<8sQI")
    if len(payload) <= header_size:
        raise ValueError("icon gallery worker response is truncated")
    magic, raw_size, item_count = struct.unpack("<8sQI", payload[:header_size])
    if (
        magic != ICON_GALLERY_WIRE_MAGIC
        or not 0 < raw_size <= MAX_ICON_GALLERY_BUNDLE_BYTES
        or not 0 <= item_count <= MAX_ICON_GALLERY_RESULTS
        or len(payload) != header_size + raw_size
    ):
        raise ValueError("icon gallery worker response is invalid")
    raw = payload[header_size:]
    if not raw:
        raise ValueError("icon gallery worker omitted its memory bundle")
    return IconGalleryMemoryBundle(raw, item_count)


def _render_icon_png_for_display_decoded(
    decoded: tuple[int, int, list[bytes]],
    destination: Path,
    target_size: int,
    *,
    fit_art_at_scale: float | None,
    render_metadata: dict[str, Any] | None,
) -> bool:
    """Render a decoded icon; split out so gallery cache helpers stay top-level."""

    width, height, rows = decoded
    source_width, source_height = width, height
    source_rows = list(rows)
    source_bbox = _display_artwork_rgba_bbox(source_rows, source_width, source_height)
    edge_outline_tone = dominant_edge_outline_tone(
        source_rows,
        source_width,
        source_height,
        source_bbox,
    )
    source_uses_transparency, source_uses_partial_alpha = _rgba_alpha_profile(source_rows)
    alpha_cleanup_applied = _rgba_has_dirty_transparent_rgb(source_rows)
    # Sanitation is pixel-local and never touches alpha, so (a) the visible-art
    # bbox of sanitized rows is byte-identical to source_bbox, and (b) it
    # commutes with cropping. Defer the actual pass until after the crop below:
    # large sources are then sanitized at crop size, not full canvas size.
    rows = source_rows
    bbox = source_bbox
    if bbox is None:
        return False
    visible_width = bbox[2] - bbox[0] + 1
    visible_height = bbox[3] - bbox[1] + 1
    cell_target = max(1, target_size)
    outline_padding = max(2, min(4, round(cell_target * 0.09)))
    art_target = max(1, cell_target - outline_padding * 2)
    # Upscale icons whose actual artwork is tiny within the source image. This
    # catches small logo dots inside large transparent canvases while preserving
    # deliberately modest artwork that already occupies a reasonable footprint.
    projected_visible_scale = min(
        art_target / max(1, visible_width),
        art_target / max(1, visible_height),
    )
    fitted_canvas_scale = min(
        art_target / max(1, width),
        art_target / max(1, height),
    )
    projected_canvas_footprint = max(visible_width, visible_height) * fitted_canvas_scale
    fit_visible_art = (
        fit_art_at_scale is not None
        and fit_art_at_scale > 1.0
        and projected_visible_scale >= fit_art_at_scale
    )
    upscaled = False
    upscale_scale_x = 1.0
    upscale_scale_y = 1.0
    if projected_canvas_footprint < art_target * 0.72 or fit_visible_art:
        crop_width, crop_height, crop_rows = _crop_rgba(rows, width, bbox)
        crop_bbox = _visible_rgba_bbox(crop_rows, crop_width, crop_height)
        if crop_bbox is not None:
            crop_width, crop_height, crop_rows, _crop_bbox = _pad_source_if_edge_touched(
                crop_rows,
                crop_width,
                crop_height,
                crop_bbox,
                min(3, outline_padding),
            )
        crop_rows = _sanitize_fully_transparent_rgb(crop_rows)
        scale = min(art_target / max(1, crop_width), art_target / max(1, crop_height))
        scaled_width = max(1, min(art_target, int(round(crop_width * scale))))
        scaled_height = max(1, min(art_target, int(round(crop_height * scale))))
        upscaled = scaled_width > crop_width or scaled_height > crop_height
        if upscaled:
            upscale_scale_x = scaled_width / crop_width
            upscale_scale_y = scaled_height / crop_height
        rows = _resize_rgba_for_icon(
            crop_rows, crop_width, crop_height, scaled_width, scaled_height
        )
        width, height = scaled_width, scaled_height
    elif max(width, height) != art_target:
        rows = _sanitize_fully_transparent_rgb(rows)
        width, height, rows, bbox = _pad_source_if_edge_touched(
            rows,
            width,
            height,
            bbox,
            min(3, outline_padding),
        )
        scale = min(art_target / max(1, width), art_target / max(1, height))
        scaled_width = max(1, min(art_target, int(round(width * scale))))
        scaled_height = max(1, min(art_target, int(round(height * scale))))
        upscaled = scaled_width > width or scaled_height > height
        if upscaled:
            upscale_scale_x = scaled_width / width
            upscale_scale_y = scaled_height / height
        rows = _resize_rgba_for_icon(rows, width, height, scaled_width, scaled_height)
        width, height = scaled_width, scaled_height
    else:
        rows = _sanitize_fully_transparent_rgb(rows)
    rendered_art_width, rendered_art_height = width, height
    rows = _smooth_binary_alpha_edges(rows, width, height)
    width, height, rows = _pad_rgba(rows, width, height, outline_padding)

    canvas = [bytearray(cell_target * 4) for _ in range(cell_target)]
    offset_x = max(0, (cell_target - width) // 2)
    offset_y = max(0, (cell_target - height) // 2)
    # Paste whole rows with one slice copy each instead of a per-pixel Python
    # loop; offset_x >= 0 and offset_x + copy_width <= cell_target by
    # construction, so the slice always lands inside the canvas row.
    copy_width = min(width, cell_target)
    copy_height = min(height, cell_target)
    paste_start = offset_x * 4
    for y in range(copy_height):
        canvas[offset_y + y][paste_start : paste_start + copy_width * 4] = rows[y][: copy_width * 4]

    outline_result: list[str] = []
    final_rows = add_adaptive_outline_to_rgba(
        [bytes(row) for row in canvas],
        cell_target,
        cell_target,
        outline_result=outline_result,
        forced_tone=edge_outline_tone,
    )
    write_rgba_png(destination, cell_target, cell_target, final_rows)
    if render_metadata is not None and render_metadata.pop("_emit_compact", False):
        compact_size = compact_gallery_size(target_size)
        compact_path = compact_icon_path(destination, target_size)
        write_rgba_png(compact_path, compact_size, compact_size,
                       _scale_rgba_nearest(final_rows, cell_target, cell_target, compact_size, compact_size))
        parent_stat, compact_stat = destination.stat(), compact_path.stat()
        write_icon_render_metadata(compact_path, {
            "parent": destination.name, "parent_stat": [parent_stat.st_mtime_ns, parent_stat.st_size],
            "resource_size": target_size, "revision": COMPACT_ICON_REVISION,
            "display_stat": [compact_stat.st_mtime_ns, compact_stat.st_size]})
    if render_metadata is not None:
        render_metadata["has_visual_detail"] = rgba_rows_have_visual_detail(final_rows, cell_target, cell_target)
        source_visible_width = source_bbox[2] - source_bbox[0] + 1 if source_bbox else 0
        source_visible_height = source_bbox[3] - source_bbox[1] + 1 if source_bbox else 0
        render_metadata.update(
            {
                "schema": 1,
                "icon_extraction_policy_revision": ICON_EXTRACTION_POLICY_REVISION,
                "resampling_policy": ICON_RESAMPLING_POLICY,
                "source_canvas_width": source_width,
                "source_canvas_height": source_height,
                "source_visible_width": source_visible_width,
                "source_visible_height": source_visible_height,
                "source_uses_transparency": source_uses_transparency,
                "source_uses_partial_alpha": source_uses_partial_alpha,
                "alpha_cleanup_applied": alpha_cleanup_applied,
                "upscaled": upscaled,
                "upscale_scale_x": upscale_scale_x,
                "upscale_scale_y": upscale_scale_y,
                "rendered_art_width": rendered_art_width,
                "rendered_art_height": rendered_art_height,
                "adaptive_outline_revision": ADAPTIVE_OUTLINE_REVISION,
                "adaptive_outline_applied": bool(outline_result),
                "adaptive_outline_tone": outline_result[-1] if outline_result else "none",
                "output_width": cell_target,
                "output_height": cell_target,
            }
        )
    return True


def dominant_edge_outline_tone(
    rows: Sequence[bytes],
    width: int,
    height: int,
    bbox: tuple[int, int, int, int] | None,
) -> str | None:
    """Choose contrast for edge-touching art, weighted by visible alpha coverage."""

    if bbox is None or not (
        bbox[0] == 0 or bbox[1] == 0 or bbox[2] == width - 1 or bbox[3] == height - 1
    ):
        return None
    return _dominant_artwork_outline_tone(rows, width)


def _dominant_artwork_outline_tone(rows: Sequence[bytes], width: int) -> str | None:
    """Classify mostly white/black artwork by its visible alpha coverage."""

    visible_weight = near_white_weight = near_black_weight = 0
    for row in rows:
        for index in range(0, min(len(row), width * 4), 4):
            red = row[index]
            green = row[index + 1]
            blue = row[index + 2]
            alpha = row[index + 3]
            if alpha <= 24:
                continue
            # A 25%-opaque white fringe must not vote as strongly as an opaque
            # colored pixel, and fully transparent stored RGB must not vote at
            # all. Weighting mirrors what the composited icon actually shows.
            visible_weight += alpha
            luminance = (red * 299 + green * 587 + blue * 114) // 1000
            if luminance >= 230 and min(red, green, blue) >= 215:
                near_white_weight += alpha
            if luminance <= 38 and max(red, green, blue) <= 52:
                near_black_weight += alpha
    if visible_weight < 6 * 64:
        return None
    if near_white_weight / visible_weight > 0.70:
        return "dark"
    if near_black_weight / visible_weight > 0.70:
        return "light"
    return None


def add_adaptive_outline_to_rgba(
    rows: Sequence[bytes],
    width: int,
    height: int,
    *,
    outline_result: list[str] | None = None,
    forced_tone: str | None = None,
) -> list[bytes]:
    # A byte mask is denser than width*height bool references. Direct row
    # indexing also avoids a helper call and temporary RGBA tuple per pixel.
    visible = [bytearray(width) for _y in range(height)]
    luminances: list[int] = []
    neutral_samples = 0
    for y, source_row in enumerate(rows):
        visible_row = visible[y]
        for x in range(width):
            index = x * 4
            red = source_row[index]
            green = source_row[index + 1]
            blue = source_row[index + 2]
            alpha = source_row[index + 3]
            if alpha <= 24:
                continue
            visible_row[x] = 1
            if alpha >= 64:
                luminances.append((red * 299 + green * 587 + blue * 114) // 1000)
                if max(red, green, blue) - min(red, green, blue) <= 24:
                    neutral_samples += 1
    if len(luminances) < 6:
        return list(rows)
    if forced_tone == "dark":
        outline = (15, 23, 42, 165)
        outline_tone = "dark"
    elif forced_tone == "light":
        outline = (255, 255, 255, 155)
        outline_tone = "light"
    else:
        # Averages are misleading for colorful icons: unrelated hues can average
        # to gray. Outline only genuinely near-neutral, low-variation artwork.
        # Even a small deliberate color accent or strong black/white detail is
        # enough evidence that the icon supplies its own contrast.
        if neutral_samples / len(luminances) < 0.995:
            return list(rows)
        if max(luminances) - min(luminances) > 64:
            return list(rows)
        average_luminance = sum(luminances) / len(luminances)
        if average_luminance >= 185:
            outline = (15, 23, 42, 165)
            outline_tone = "dark"
        elif average_luminance <= 70:
            outline = (255, 255, 255, 155)
            outline_tone = "light"
        else:
            return list(rows)
    outline_red, outline_green, outline_blue, outline_alpha = outline
    # The expensive neighborhood search cannot affect pixels more than two
    # pixels from this exact visibility mask. Byte searches avoid another
    # Python per-pixel pass, and the untouched rows remain byte-identical.
    min_x, min_y, max_x, max_y = width, height, -1, -1
    for y, visible_row in enumerate(visible):
        first = visible_row.find(b"\x01")
        if first >= 0:
            min_x = min(min_x, first)
            max_x = max(max_x, visible_row.rfind(b"\x01"))
            min_y = min(min_y, y)
            max_y = y
    output = list(rows)
    outlined_pixels = 0
    for y in range(max(0, min_y - 2), min(height, max_y + 3)):
        row = bytearray(rows[y])
        for x in range(max(0, min_x - 2), min(width, max_x + 3)):
            if visible[y][x]:
                continue
            nearest = 0
            for radius in (1, 2):
                found = False
                for yy in range(max(0, y - radius), min(height, y + radius + 1)):
                    for xx in range(max(0, x - radius), min(width, x + radius + 1)):
                        if visible[yy][xx]:
                            found = True
                            break
                    if found:
                        break
                if found:
                    nearest = radius
                    break
            if not nearest:
                continue
            alpha = outline_alpha if nearest == 1 else max(45, outline_alpha // 3)
            index = x * 4
            row[index : index + 4] = bytes((outline_red, outline_green, outline_blue, alpha))
            outlined_pixels += 1
        output[y] = bytes(row)
    if outline_result is not None and outlined_pixels:
        outline_result.append(outline_tone)
    return output


def decode_console_output(data: bytes) -> str:
    """Decode Windows CLI output, including occasional BOM-less UTF-16LE."""
    if not data:
        return ""
    if data.startswith((b"\xff\xfe", b"\xfe\xff")):
        return data.decode("utf-16", errors="replace")
    sample = data[:200]
    if sample.count(b"\x00") > max(2, len(sample) // 6):
        return data.decode("utf-16-le", errors="replace")
    for encoding in ("utf-8", locale.getpreferredencoding(False), "cp1252"):
        try:
            return data.decode(encoding)
        except (UnicodeDecodeError, LookupError):
            pass
    return data.decode("utf-8", errors="replace")


def clean_output(text: str) -> str:
    """Remove terminal control artifacts without copying already-clean output."""

    if "\x1b" in text:
        text = ANSI_RE.sub("", text)
    if "\r" in text:
        text = text.replace("\r", "")
    if "\x08" in text:
        text = text.replace("\x08", "")
    return text


# ==================== Windows identity, registry, and AppX ====================

def is_admin() -> bool:
    if os.name != "nt":
        return False
    try:
        return bool(_SHELL32.IsUserAnAdmin())
    except (AttributeError, OSError):
        return False


def windows_token_elevation_type() -> str:
    """Return the Windows split-token state without exposing account identity."""

    if os.name != "nt":
        return "unknown"
    token_query = 0x0008
    token_elevation_type_class = 18
    names = {1: "default", 2: "full", 3: "limited"}
    token = ctypes.c_void_p()
    try:
        kernel32 = ctypes.WinDLL("kernel32", use_last_error=True)
        advapi32 = ctypes.WinDLL("advapi32", use_last_error=True)
        kernel32.GetCurrentProcess.restype = ctypes.c_void_p
        kernel32.CloseHandle.argtypes = [ctypes.c_void_p]
        kernel32.CloseHandle.restype = ctypes.c_int
        advapi32.OpenProcessToken.argtypes = [
            ctypes.c_void_p,
            ctypes.c_uint32,
            ctypes.POINTER(ctypes.c_void_p),
        ]
        advapi32.OpenProcessToken.restype = ctypes.c_int
        advapi32.GetTokenInformation.argtypes = [
            ctypes.c_void_p,
            ctypes.c_int,
            ctypes.c_void_p,
            ctypes.c_uint32,
            ctypes.POINTER(ctypes.c_uint32),
        ]
        advapi32.GetTokenInformation.restype = ctypes.c_int
        if not advapi32.OpenProcessToken(
            kernel32.GetCurrentProcess(), token_query, ctypes.byref(token)
        ):
            return "unknown"
        elevation_type = ctypes.c_uint32()
        returned = ctypes.c_uint32()
        if not advapi32.GetTokenInformation(
            token,
            token_elevation_type_class,
            ctypes.byref(elevation_type),
            ctypes.sizeof(elevation_type),
            ctypes.byref(returned),
        ):
            return "unknown"
        return names.get(int(elevation_type.value), "unknown")
    except (AttributeError, OSError, TypeError, ValueError):
        return "unknown"
    finally:
        if token.value:
            with contextlib.suppress(OSError):
                kernel32.CloseHandle(token)


def current_account_fingerprint() -> str:
    account = "\\".join(
        part
        for part in (
            os.environ.get("USERDOMAIN", ""),
            os.environ.get("USERNAME", ""),
        )
        if part
    )
    if not account:
        return "unknown"
    return hashlib.sha256(account.casefold().encode("utf-8")).hexdigest()[:16]


def single_instance_mutex_name() -> str:
    return f"Local\\{APP_NAME}-{current_account_fingerprint()}-interactive"


def pending_reboot_reasons() -> list[str]:
    """Best-effort reboot preflight using indicators readable without elevation."""
    if os.name != "nt":
        return []
    import winreg

    reasons: list[str] = []
    for subkey, label in (
        (
            r"SOFTWARE\Microsoft\Windows\CurrentVersion\Component Based Servicing\RebootPending",
            "Windows servicing",
        ),
        (
            r"SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\RebootRequired",
            "Windows Update",
        ),
    ):
        try:
            with winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, subkey):
                reasons.append(label)
        except OSError:
            pass
    try:
        with winreg.OpenKey(
            winreg.HKEY_LOCAL_MACHINE,
            r"SYSTEM\CurrentControlSet\Control\Session Manager",
        ) as key:
            value, _value_type = winreg.QueryValueEx(key, "PendingFileRenameOperations")
            if value:
                reasons.append("pending file replacements")
    except OSError:
        pass
    return reasons


@functools.lru_cache(maxsize=1)
def system_boot_id() -> int | None:
    """Read Windows' successful-boot counter once per process, never from wall time."""

    if os.name != "nt":
        return None
    try:
        import winreg

        with winreg.OpenKey(
            winreg.HKEY_LOCAL_MACHINE,
            r"SYSTEM\CurrentControlSet\Control\Session Manager\Memory Management\PrefetchParameters",
        ) as key:
            value, kind = winreg.QueryValueEx(key, "BootId")
        return value if kind == winreg.REG_DWORD and valid_system_boot_id(value) else None
    except (AttributeError, OSError, TypeError, ValueError):
        return None


def valid_system_boot_id(value: Any) -> bool:
    return type(value) is int and 0 <= value <= 0xFFFFFFFF


def restarted_after_pending_marker(
    record: Mapping[str, Any],
    *,
    boot_id: int | None = None,
) -> bool:
    """Require a later successful boot; missing/reset counters remain unverified."""

    current_boot = system_boot_id() if boot_id is None else boot_id
    recorded_boot = record.get("boot_id")
    return (
        valid_system_boot_id(current_boot) and valid_system_boot_id(recorded_boot)
        and current_boot > recorded_boot
    )


@dataclasses.dataclass(slots=True, frozen=True)
class RegistryInstallEntry:
    display_name: str
    display_version: str
    scope: str
    technology: str
    install_location: str = ""
    display_icon: str = ""
    uninstall_command: str = ""
    uninstall_key: str = ""
    product_code: str = ""
    estimated_size_kb: int | None = None
    installed_date: str = ""
    installed_timestamp: str = ""
    installed_timestamp_precision: str = ""
    installed_date_source: str = ""
    registration_changed_date: str = ""
    registration_changed_at: str = ""


def registry_estimated_size_kb(value: Any) -> int | None:
    try:
        size = int(value)
    except (TypeError, ValueError):
        return None
    return size if size > 0 else None


def normalized_registry_install_date(value: Any) -> str:
    """Return an ISO date only for complete, valid uninstall metadata dates."""

    raw = str(value).strip()
    if re.fullmatch(r"\d{8}", raw):
        raw = f"{raw[:4]}-{raw[4:6]}-{raw[6:]}"
    if not re.fullmatch(r"\d{4}-\d{2}-\d{2}", raw):
        return ""
    try:
        return dt.date.fromisoformat(raw).isoformat()
    except ValueError:
        return ""


def registry_key_last_write_timestamp(key: Any) -> str:
    """Return the uninstall key's UTC FILETIME without discarding microseconds."""

    if os.name != "nt":
        return ""
    import winreg

    try:
        filetime = int(winreg.QueryInfoKey(key)[2])
        changed_utc = dt.datetime(1601, 1, 1, tzinfo=dt.UTC) + dt.timedelta(
            microseconds=filetime // 10
        )
        return changed_utc.isoformat(timespec="microseconds")
    except (OSError, OverflowError, TypeError, ValueError):
        return ""


def corroborated_local_service_date(
    paths: Sequence[Path],
) -> tuple[str, str, tuple[str, ...]]:
    """Infer a date only when two distinct local objects corroborate it.

    Windows creation timestamps are useful deployment clues, but they are not an
    authoritative installation ledger. This intentionally bounded helper accepts
    only same-day or adjacent-day agreement and leaves every other case unknown.
    """

    dated_paths: list[tuple[dt.date, float, str]] = []
    seen: set[str] = set()
    today = dt.date.today()
    for path in paths:
        try:
            resolved = path.resolve(strict=True)
            key = os.path.normcase(str(resolved))
            if key in seen:
                continue
            seen.add(key)
            timestamp = resolved.stat().st_ctime
            observed = dt.datetime.fromtimestamp(timestamp).date()
        except (OSError, OverflowError, ValueError):
            continue
        if dt.date(2000, 1, 1) <= observed <= today + dt.timedelta(days=1):
            dated_paths.append((observed, timestamp, str(resolved)))
    if len(dated_paths) < 2:
        return "", "", ()
    dated_paths.sort(key=lambda record: record[0])
    for start in range(len(dated_paths) - 1):
        left_date, left_timestamp, left_path = dated_paths[start]
        right_date, right_timestamp, right_path = dated_paths[start + 1]
        if (right_date - left_date).days <= 1:
            return (
                right_date.isoformat(),
                epoch_storage_timestamp(max(left_timestamp, right_timestamp)),
                (left_path, right_path),
            )
    return "", "", ()


def installed_item_date_identity(item: UpdateItem) -> tuple[str, str, str, str, str]:
    """Match one installed package across the Updates and All packages catalogs."""

    return (
        item.provider.casefold(),
        item.package_id.casefold(),
        item.scope.casefold(),
        item.source.casefold(),
        item.current.casefold(),
    )


def reuse_cached_service_dates(
    items: Sequence[UpdateItem], cached_items: Sequence[UpdateItem],
) -> int:
    """Reuse idle evidence for the same installation, never replacing fresh dates."""

    def identity(item: UpdateItem) -> tuple[Any, ...]:
        return (
            *installed_item_date_identity(item), item.installed_location,
            item.installed_registration_changed_at, item.product_codes,
        )

    evidence = {
        identity(item): item for item in cached_items
        if item.provider != PORTABLE_PROVIDER_KEY and item.installed_date
        and item.installed_date_source.startswith((
            "Corroborated local install-folder creation times",
            "Windows Package.InstalledDate (installed or last updated)",
        ))
    }
    changed = 0
    for item in items:
        previous = evidence.get(identity(item))
        if previous is None or item.installed_date or item.installed_timestamp:
            continue
        for field in (
            "installed_date", "installed_timestamp", "installed_timestamp_precision",
            "installed_date_is_estimate", "installed_date_source",
        ):
            setattr(item, field, getattr(previous, field))
        changed += 1
    return changed


def local_date_sleuth_paths(item: UpdateItem) -> tuple[Path, ...]:
    """Infer only within an inventory-supplied install folder, never an artwork root."""

    if item.provider != "winget" or item.scope == "portable" or not item.installed_location:
        return ()
    source: Path | None = None
    if item.icon_source:
        try:
            candidate_source = Path(os.path.expandvars(item.icon_source)).resolve(strict=True)
            if candidate_source.suffix.casefold() in {".exe", ".dll"} and candidate_source.is_file():
                source = candidate_source
        except (OSError, RuntimeError):
            pass
    try:
        location = Path(os.path.expandvars(item.installed_location)).resolve(strict=True)
    except (OSError, RuntimeError):
        return ()
    if not location.is_dir() or len(location.parts) < 3:
        return ()
    folded_location = os.path.normcase(str(location))
    windows_root = os.path.normcase(os.environ.get("WINDIR", r"C:\Windows"))
    if folded_location in {
        os.path.normcase(os.environ.get("ProgramFiles", r"C:\Program Files")),
        os.path.normcase(os.environ.get("ProgramFiles(x86)", r"C:\Program Files (x86)")),
        windows_root,
        os.path.normcase(os.path.join(windows_root, "System32")),
        os.path.normcase(os.path.join(windows_root, "SysWOW64")),
    }:
        return ()
    if folded_location.startswith(os.path.normcase(str(icon_cache_dir())) + os.sep):
        return ()

    candidates = [location]
    if source is not None and source.is_relative_to(location):
        candidates.append(source)
    if len(candidates) >= 2:
        return tuple(candidates)

    identity = normalized_package_name(item.name)
    best: tuple[int, Path] | None = None
    try:
        for index, entry in enumerate(location.iterdir()):
            if index >= 96:
                break
            if not entry.is_file() or entry.suffix.casefold() not in {".exe", ".dll"}:
                continue
            stem = normalized_package_name(entry.stem)
            if not stem or stem.startswith(("unins", "uninstall", "setup", "update")):
                continue
            score = 2 if stem == identity else 1 if stem in identity or identity in stem else 0
            if score and (best is None or score > best[0]):
                best = (score, entry)
    except OSError:
        return tuple(candidates)
    if best is not None:
        # A link to a payload outside this install folder is not date evidence.
        with contextlib.suppress(OSError, RuntimeError):
            payload = best[1].resolve(strict=True)
            if payload.is_relative_to(location):
                candidates.append(payload)
    return tuple(candidates)


def human_size_from_kb(size_kb: int | None) -> str:
    if not size_kb or size_kb <= 0:
        return ""
    value = float(size_kb)
    for unit in ("KB", "MB", "GB", "TB"):
        if value < 1024 or unit == "TB":
            break
        value /= 1024
    if unit == "KB":
        return f"{value:.0f} {unit}"
    return f"{value:.1f} {unit}"


def strip_display_icon_index(value: str) -> str:
    r"""Extract a filesystem path from ARP DisplayIcon values.

    DisplayIcon commonly contains quoted paths and optional icon indexes, for
    example `"C:\Program Files\App\app.exe",0` or `C:\Path\app.ico`.
    """

    raw = os.path.expandvars(value.strip())
    if not raw:
        return ""
    if raw.startswith('"'):
        end = raw.find('"', 1)
        if end > 1:
            return raw[1:end]
    # ARP publishers commonly leave paths containing spaces unquoted. Match
    # the complete icon path before asking shlex to split anything; otherwise
    # ``C:\Program Files\App\app.exe`` is truncated to ``C:\Program`` and
    # icon discovery silently falls back to a less relevant executable.
    match = re.match(
        r"^(?P<path>.+\.(?:exe|dll|ico|png))(?:,\s*-?\d+)?$",
        raw,
        re.IGNORECASE,
    )
    if match:
        return match.group("path").strip().strip('"')
    with contextlib.suppress(ValueError):
        parts = shlex.split(raw, posix=False)
        if parts:
            raw = parts[0]
    match = re.match(
        r"^(?P<path>.+?\.(?:exe|dll|ico|png))(?:,\s*-?\d+)?$",
        raw,
        re.IGNORECASE,
    )
    if match:
        return match.group("path").strip().strip('"')
    return raw.split(",", 1)[0].strip().strip('"')


def resolve_indirect_icon_path(value: str) -> Path | None:
    """Resolve a documented Shell indirect-resource string to a local file."""

    raw = os.path.expandvars(value.strip())
    if os.name != "nt" or not raw.startswith("@"):
        return None
    try:
        shlwapi = ctypes.WinDLL("shlwapi", use_last_error=True)
        load_indirect = shlwapi.SHLoadIndirectString
    except (AttributeError, OSError):
        return None
    load_indirect.argtypes = [
        ctypes.c_wchar_p,
        ctypes.c_wchar_p,
        ctypes.c_uint,
        ctypes.c_void_p,
    ]
    load_indirect.restype = ctypes.c_long
    output = ctypes.create_unicode_buffer(32_768)
    try:
        result = int(load_indirect(raw, output, len(output), None))
    except OSError:
        return None
    if result < 0:
        return None
    resolved = Path(os.path.expandvars(output.value.strip().strip('"')))
    return resolved if resolved.is_file() else None


def resolve_registered_app_path(value: str) -> Path | None:
    """Resolve a bare executable name through Windows' documented App Paths registry."""

    raw = value.strip().strip('"')
    candidate = Path(raw)
    if (
        os.name != "nt"
        or candidate.name != raw
        or candidate.suffix.casefold() != ".exe"
    ):
        return None
    import winreg

    subkey = rf"Software\Microsoft\Windows\CurrentVersion\App Paths\{candidate.name}"
    registry_views = tuple(
        dict.fromkeys((0, int(getattr(winreg, "KEY_WOW64_32KEY", 0))))
    )
    for hive in (winreg.HKEY_CURRENT_USER, winreg.HKEY_LOCAL_MACHINE):
        for registry_view in registry_views:
            try:
                with winreg.OpenKey(
                    hive,
                    subkey,
                    0,
                    winreg.KEY_READ | registry_view,
                ) as key:
                    registered = str(registry_value(key, "", "")).strip().strip('"')
            except OSError:
                continue
            path = Path(os.path.expandvars(registered))
            if path.is_file():
                return path
    return None


def _xml_local_name(name: str) -> str:
    return name.rsplit("}", 1)[-1]


@functools.lru_cache(maxsize=4096)
def _appx_asset_dimensions_cached(
    path_text: str,
    modified_ns: int,
    file_size: int,
) -> tuple[int, int] | None:
    """Cache immutable AppX asset headers while retaining replacement safety."""

    del modified_ns, file_size  # Their values deliberately participate in the cache key.
    return png_dimensions_fast(Path(path_text))


def _appx_asset_dimensions(path: Path) -> tuple[int, int] | None:
    try:
        stat = path.stat()
    except OSError:
        return None
    return _appx_asset_dimensions_cached(
        os.path.normcase(str(path)),
        int(stat.st_mtime_ns),
        int(stat.st_size),
    )


def _appx_asset_score(
    path: Path,
    target_size: int,
    nominal_size: int = 0,
) -> tuple[int, int, int, int, int, str]:
    name = path.name.casefold()
    parent = path.parent.name.casefold()
    text = f"{parent}.{name}"
    scale = 100
    target = 0
    if match := re.search(r"(?:^|[._-])scale-(\d+)(?:[._-]|$)", text):
        scale = int(match.group(1))
    if match := re.search(r"(?:^|[._-])targetsize-(\d+)(?:[._-]|$)", text):
        target = int(match.group(1))
    nominal = 0
    if match := re.search(r"square(\d+)x\1", name):
        nominal = int(match.group(1))
    dimensions = None if target or nominal_size else _appx_asset_dimensions(path)
    if target:
        physical = target
        area = physical * physical
    elif nominal_size:
        physical = max(1, int(nominal_size * scale / 100))
        area = physical * physical
    elif dimensions is not None:
        physical = max(dimensions)
        area = dimensions[0] * dimensions[1]
    else:
        physical = target or int(nominal * scale / 100) or scale
        area = physical * physical
    unplated = 1 if "altform-unplated" in text or "altform-lightunplated" in text else 0
    default_contrast = 0 if "contrast-" in text else 1
    meets_target = 1 if physical >= target_size else 0
    # Within the same manifest logo family and presentation preference, choose
    # the least expensive asset that meets the real display target. If none
    # meets it, choose the largest available input to minimize enlargement.
    # This avoids decoding 1240px tiles for a 144px Details image.
    size_rank = -physical if meets_target else physical
    area_rank = -area if meets_target else area
    # Preserve the existing preference for transparent/unplated identity art,
    # but within that presentation family prefer the normal asset over a
    # forced black/white accessibility variant when both are available.
    return (
        unplated,
        default_contrast,
        meets_target,
        size_rank,
        area_rank,
        path.name.casefold(),
    )


_APPX_ASSET_QUALIFIER_START = re.compile(
    r"(?i)[._-](?:(?:scale|targetsize)-\d+|altform-(?:unplated|lightunplated)|contrast-(?:black|white))"
)


def _appx_asset_family_stem(path: Path) -> str:
    """Return the logical AppX asset stem beneath Windows qualifiers.

    A resolved source commonly arrives as an already-qualified filename such
    as ``Logo.targetsize-256_altform-unplated.png``.  Expanding that literal
    stem sees only its contrast siblings, not the rest of the ``Logo`` family.
    Icon Lineup needs the complete local family, while its later bounded
    sampler and visual deduplicator keep the result compact.
    """

    match = _APPX_ASSET_QUALIFIER_START.search(path.stem)
    return path.stem[: match.start()] if match is not None else path.stem


def _appx_asset_variants(logical_path: Path) -> list[Path]:
    variants: dict[str, Path] = {}
    try:
        if logical_path.exists():
            variants[os.path.normcase(str(logical_path))] = logical_path
        parent = logical_path.parent
        stem = _appx_asset_family_stem(logical_path)
        suffix = logical_path.suffix or ".png"
        for candidate in parent.glob(f"{stem}*{suffix}"):
            if candidate.is_file():
                variants[os.path.normcase(str(candidate))] = candidate
        for qualifier_dir in parent.iterdir():
            if not qualifier_dir.is_dir():
                continue
            candidate = qualifier_dir / logical_path.name
            if candidate.exists():
                variants[os.path.normcase(str(candidate))] = candidate
    except OSError:
        return []
    return list(variants.values())


def _appx_gallery_variant_sample(
    primary: Path,
    variants: Sequence[Path],
    limit: int = 16,
) -> tuple[Path, ...]:
    """Choose a bounded, presentation-diverse sample from an AppX family.

    Store packages can ship well over a hundred scale/target-size variants.
    Taking the filesystem's first sixteen both misses the useful large art and
    over-represents one qualifier.  This keeps the selected source, samples the
    best local rendition of every plating/contrast presentation, then fills
    remaining slots with useful native sizes.  The gallery worker still does
    exact and conservative visual deduplication afterward.
    """

    if limit <= 0:
        return ()
    unique: dict[str, Path] = {}
    for path in (primary, *variants):
        with contextlib.suppress(OSError):
            if path.is_file():
                unique.setdefault(os.path.normcase(str(path.resolve())), path)
    if not unique:
        return ()

    selected: list[Path] = []
    selected_keys: set[str] = set()

    def add(path: Path) -> None:
        key = os.path.normcase(str(path.resolve()))
        if key not in selected_keys and len(selected) < limit:
            selected_keys.add(key)
            selected.append(path)

    if primary.is_file():
        add(primary)

    def presentation(path: Path) -> tuple[str, str]:
        name = path.name.casefold()
        plating = (
            "light-unplated"
            if "altform-lightunplated" in name
            else "unplated"
            if "altform-unplated" in name
            else "plated"
        )
        contrast = (
            "black"
            if "contrast-black" in name
            else "white"
            if "contrast-white" in name
            else "default"
        )
        return plating, contrast

    by_presentation: dict[tuple[str, str], list[Path]] = {}
    for path in unique.values():
        by_presentation.setdefault(presentation(path), []).append(path)
    presentation_order = (
        ("plated", "default"),
        ("unplated", "default"),
        ("light-unplated", "default"),
        ("plated", "black"),
        ("plated", "white"),
        ("unplated", "black"),
        ("unplated", "white"),
        ("light-unplated", "black"),
        ("light-unplated", "white"),
    )
    for profile in presentation_order:
        choices = by_presentation.get(profile, ())
        if choices:
            add(max(choices, key=lambda path: _appx_asset_score(path, 256)))

    physical_sizes: dict[Path, int] = {}
    for path in unique.values():
        name = path.name.casefold()
        match = re.search(r"(?:^|[._-])targetsize-(\d+)(?:[._-]|$)", name)
        dimensions = None if match else png_dimensions_fast(path)
        physical_sizes[path] = int(match.group(1)) if match else max(dimensions or (0, 0))

    # Spend any remaining budget on a useful progression of native target
    # sizes, preferring normal-contrast representations at each milestone.
    for desired_size in (16, 24, 32, 48, 64, 96, 128, 256):
        if len(selected) >= limit:
            break

        def milestone_rank(path: Path) -> tuple[int, int, int, str]:
            profile = presentation(path)
            return (
                -abs(physical_sizes[path] - desired_size),
                1 if profile[1] == "default" else 0,
                1 if profile[0] == "unplated" else 0,
                path.name.casefold(),
            )

        remaining = [
            path
            for key, path in unique.items()
            if key not in selected_keys
        ]
        if remaining:
            add(max(remaining, key=milestone_rank))
    return tuple(selected)


def _best_appx_logo_candidate(
    candidates: Sequence[tuple[int, tuple[int, int, int, int, int, str], Path]],
) -> Path | None:
    """Choose the best manifest asset that contains recognizable artwork.

    Some desktop bridge and shell-extension packages declare a high-priority
    Square150x150 tile that is only a blank plating surface while their real
    logo lives in a lower-priority Square44 target-size family. Source
    resolution runs in the background, so decoding these few local PNGs does
    not touch Tk's event thread. Undecodable formats remain eligible for the
    renderer's GDI+ fallback; positively blank PNGs do not.
    """

    # Resolution sufficiency comes first: never trade a target-sized tile for
    # an undersized unplated mark. Among candidates that both meet the actual
    # display target (or among equally undersized fallbacks), Windows'
    # ``altform-unplated`` designation is useful presentation intent, not a
    # blanket preference for transparency. This keeps a sparsely plated tile
    # from outranking an equally sharp AppList mark without promoting tiny art.
    def rank(
        entry: tuple[int, tuple[int, int, int, int, int, str], Path],
    ) -> tuple[int, int, int, int, int, int, str]:
        priority, score, _path = entry
        unplated, default_contrast, meets_target, size_rank, area_rank, name = score
        if meets_target:
            return (
                1,
                unplated,
                default_contrast,
                priority,
                size_rank,
                area_rank,
                name,
            )
        # No candidate is large enough. Resolution is now the primary
        # fallback criterion: choosing a preferred presentation at 256px over
        # equally valid 300px/620px artwork would unnecessarily blur extreme-
        # DPI Details views. Presentation intent breaks only resolution ties.
        return (
            0,
            size_rank,
            area_rank,
            unplated,
            default_contrast,
            priority,
            name,
        )

    for candidate in sorted(candidates, key=rank, reverse=True):
        if icon_png_has_visual_detail(candidate[2]) is not False:
            return candidate[2]
    return None


_APPX_REPOSITORY_LOCK = threading.Lock()
_APPX_REPOSITORY_BUILT_AT = 0.0
_APPX_REPOSITORY_ENTRIES: tuple[tuple[str, str, Path], ...] = ()


def _installed_appx_repository_entries() -> tuple[tuple[str, str, Path], ...]:
    """Return installed AppX identities and their authoritative package roots.

    Desktop-bridge packages are not required to live beneath WindowsApps. The
    per-user AppModel repository is both cheaper and more accurate than a
    filesystem crawl, and its short TTL lets installs made during a long GUI
    session appear on a later scan.
    """

    global _APPX_REPOSITORY_BUILT_AT, _APPX_REPOSITORY_ENTRIES
    if os.name != "nt":
        return ()
    now = time.monotonic()
    with _APPX_REPOSITORY_LOCK:
        if _APPX_REPOSITORY_ENTRIES and now - _APPX_REPOSITORY_BUILT_AT < 30.0:
            return _APPX_REPOSITORY_ENTRIES
        import winreg

        entries: list[tuple[str, str, Path]] = []
        repository = (
            r"Software\Classes\Local Settings\Software\Microsoft\Windows"
            r"\CurrentVersion\AppModel\Repository\Packages"
        )
        try:
            with winreg.OpenKey(winreg.HKEY_CURRENT_USER, repository) as parent:
                for index in range(winreg.QueryInfoKey(parent)[0]):
                    try:
                        full_name = winreg.EnumKey(parent, index)
                        with winreg.OpenKey(parent, full_name) as key:
                            root_value = registry_value(key, "PackageRootFolder", "")
                            display_name = str(registry_value(key, "DisplayName", "")).strip()
                        root = Path(os.path.expandvars(str(root_value).strip().strip('"')))
                        if root.is_dir():
                            entries.append((full_name, display_name, root))
                    except OSError:
                        continue
        except OSError:
            entries = []
        _APPX_REPOSITORY_ENTRIES = tuple(entries)
        _APPX_REPOSITORY_BUILT_AT = now
        return _APPX_REPOSITORY_ENTRIES


def _appx_candidate_roots(package_id: str, package_name: str) -> list[Path]:
    roots: list[Path] = []
    full_name = ""
    if package_id.casefold().startswith("msix\\"):
        full_name = package_id.split("\\", 1)[1]
        roots.extend(
            (
                Path(os.environ.get("PROGRAMFILES", r"C:\Program Files"))
                / "WindowsApps"
                / full_name,
                Path(os.environ.get("WINDIR", r"C:\Windows")) / "SystemApps" / full_name,
            )
        )

    encoded_id = (
        package_id.split("\\", 1)[1] if package_id.casefold().startswith("msix\\") else package_id
    )
    normalized_candidates = {
        normalized_package_name(value)
        for value in (encoded_id, package_name)
        if normalized_package_name(value)
    }
    scored: list[tuple[int, str, Path]] = []
    for repository_name, display_name, root in _installed_appx_repository_entries():
        identity = repository_name.split("_", 1)[0]
        normalized_identity = normalized_package_name(identity)
        normalized_display = (
            ""
            if display_name.casefold().startswith("ms-resource:")
            else normalized_package_name(display_name)
        )
        score = 0
        if full_name and repository_name.casefold() == full_name.casefold():
            score = 100
        elif normalized_identity in normalized_candidates:
            score = 90
        elif normalized_display and normalized_display in normalized_candidates:
            score = 80
        elif any(
            normalized_identity_fuzzy_match(candidate, normalized_identity)
            for candidate in normalized_candidates
        ):
            score = 50
        if score:
            scored.append((score, repository_name.casefold(), root))
    roots.extend(root for _score, _name, root in sorted(scored, reverse=True))

    unique: list[Path] = []
    seen: set[str] = set()
    for root in roots:
        key = os.path.normcase(str(root))
        if key not in seen and root.is_dir():
            seen.add(key)
            unique.append(root)
    return unique


def appx_package_install_location(package_id: str, package_name: str = "") -> Path | None:
    """Resolve an exact ``MSIX\\PackageFullName`` to its registered local root."""

    if not package_id.casefold().startswith("msix\\"):
        return None
    full_name = package_id.split("\\", 1)[1].strip()
    if not full_name:
        return None
    return next(
        (
            root
            for root in _appx_candidate_roots(package_id, package_name)
            if root.name.casefold() == full_name.casefold()
        ),
        None,
    )


def normalized_identity_fuzzy_match(candidate: str, identity: str) -> bool:
    """Allow only strong containment when bridging an alias to an AppX identity."""

    if len(candidate) < 6 or len(identity) < 6:
        return False
    # Windows occasionally inserts an identity qualifier between publisher and
    # product (Microsoft.AppInstaller -> Microsoft.DesktopAppInstaller). A long
    # display-name suffix remains strong evidence even when the full-length
    # containment ratio would be overly strict.
    if len(candidate) >= 10 and identity.endswith(candidate):
        return True
    if candidate not in identity and identity not in candidate:
        return False
    return min(len(candidate), len(identity)) / max(len(candidate), len(identity)) >= 0.55


def _loose_appx_logo_path(root: Path, target_size: int) -> Path | None:
    """Find standard loose tile assets when a bridge package has no manifest here."""

    candidates: list[tuple[int, tuple[int, int, int, int, str], Path]] = []
    search_roots = (root, root / "Assets", root / "assets")
    for asset_root in search_roots:
        if not asset_root.is_dir():
            continue
        for pattern, priority, nominal in (
            ("Square310x310Logo*.png", 3, 310),
            ("Square150x150Logo*.png", 2, 150),
            ("Square71x71Logo*.png", 1, 71),
            ("Square44x44Logo*.png", 1, 44),
            ("Store*Logo*.png", 1, 50),
        ):
            with contextlib.suppress(OSError):
                for candidate in asset_root.glob(pattern):
                    if candidate.is_file():
                        candidates.append(
                            (
                                priority,
                                _appx_asset_score(candidate, target_size, nominal),
                                candidate,
                            )
                        )
    return _best_appx_logo_candidate(candidates)


def appx_manifest_logo_path(
    package_id: str,
    target_size: int = 256,
    package_name: str = "",
) -> Path | None:
    roots = _appx_candidate_roots(package_id, package_name)
    executable_fallbacks: list[Path] = []
    for root in roots:
        manifest = root / "AppxManifest.xml"
        tree = None
        if manifest.exists():
            try:
                tree = ET.parse(manifest)
            except (OSError, ET.ParseError):
                tree = None
        logical_assets: list[tuple[int, int, str]] = []
        if tree is not None:
            for element in tree.iter():
                local_name = _xml_local_name(element.tag)
                if local_name == "DefaultTile":
                    for attribute in (
                        "Square310x310Logo",
                        "Square150x150Logo",
                        "Square71x71Logo",
                    ):
                        value = element.attrib.get(attribute, "").strip()
                        if value:
                            nominal = (
                                310 if "310" in attribute else 150 if "150" in attribute else 71
                            )
                            logical_assets.append((3 if nominal == 310 else 2, nominal, value))
                elif local_name == "VisualElements":
                    for attribute in ("Square150x150Logo", "Square44x44Logo"):
                        value = element.attrib.get(attribute, "").strip()
                        if value:
                            nominal = 150 if "150" in attribute else 44
                            logical_assets.append((2 if nominal == 150 else 1, nominal, value))
                elif local_name == "Logo" and element.text:
                    logical_assets.append((1, 0, element.text.strip()))
        candidates: list[tuple[int, tuple[int, int, int, int, str], Path]] = []
        seen_logicals: set[str] = set()
        for priority, nominal, logical in sorted(logical_assets, reverse=True):
            if not logical:
                continue
            if logical.startswith("@"):
                resolved = resolve_indirect_icon_path(logical)
                if resolved is not None:
                    candidates.append(
                        (priority, _appx_asset_score(resolved, target_size, nominal), resolved)
                    )
                continue
            if logical.startswith("ms-resource:"):
                continue
            logical_key = logical.replace("/", "\\").casefold()
            if logical_key in seen_logicals:
                continue
            seen_logicals.add(logical_key)
            base = root / logical.replace("/", "\\")
            for variant in _appx_asset_variants(base):
                candidates.append(
                    (priority, _appx_asset_score(variant, target_size, nominal), variant)
                )
        if best := _best_appx_logo_candidate(candidates):
            return best
        if loose := _loose_appx_logo_path(root, target_size):
            return loose
        executable_roots: list[Path | None] = [root]
        if root.name.casefold() in {"appx", "assets"}:
            executable_roots.append(root.parent)
        if root.name.casefold() == "appx":
            executable_roots.append(root.parent.parent)
        for executable_root in executable_roots:
            if executable_root is None:
                continue
            if fallback := install_location_icon_path(str(executable_root), package_name):
                executable_fallbacks.append(fallback)
    if executable_fallbacks:
        return executable_fallbacks[0]
    return None


def install_location_icon_path(
    location: str,
    package_name: str,
    identity_hint: str = "",
) -> Path | None:
    if not location:
        return None
    root = Path(os.path.expandvars(location.strip().strip('"')))
    if root.is_file():
        return root
    if not root.is_dir():
        return None
    normalized_name = normalized_package_name(package_name)
    if not normalized_name:
        return None
    identity_words = {
        normalized_package_name(word)
        for word in re.findall(r"[A-Za-z][A-Za-z0-9+-]*", f"{package_name} {identity_hint}")
        if len(normalized_package_name(word)) >= 2
    }
    # Many portable WinGet packages and desktop applications keep the primary
    # executable one or two folders below InstallLocation. Search only that
    # bounded neighborhood, require a package-name match, and cap entries so a
    # malformed registry path cannot turn icon discovery into a disk crawl.
    # A few installers decorate their application folder with the same icon
    # used by Explorer. Keep this as a last-resort candidate: desktop.ini can
    # describe a folder rather than the application, so a name-matched EXE or
    # ICO below must always win.
    desktop_icon = desktop_ini_icon_path(root)
    pending: deque[tuple[Path, int]] = deque(((root, 0),))
    scored: list[tuple[int, int, int, int, str, Path]] = []
    fallback_files: list[Path] = []
    visited_entries = 0
    skipped_directories = {
        "drivers",
        "locales",
        "node_modules",
        "plugins",
        "redist",
        "resources",
    }
    while pending and visited_entries < 600:
        directory, depth = pending.popleft()
        try:
            entries = list(directory.iterdir())
        except OSError:
            continue
        for path in entries:
            visited_entries += 1
            if visited_entries > 600:
                break
            try:
                if path.is_dir():
                    if depth < 2 and path.name.casefold() not in skipped_directories:
                        pending.append((path, depth + 1))
                    continue
                if not path.is_file() or path.suffix.casefold() not in {".exe", ".ico"}:
                    continue
            except OSError:
                continue
            if likely_uninstaller_icon_source(path):
                continue
            fallback_files.append(path)
            normalized_stem = normalized_package_name(path.stem)
            stem_words = {
                normalized_package_name(word)
                for word in re.findall(r"[A-Za-z][A-Za-z0-9+-]{3,}", path.stem)
            }
            match_score = 0
            if normalized_stem.endswith("gui") and normalized_name in normalized_stem:
                match_score = 5
            elif normalized_stem == normalized_name:
                match_score = 4
            elif len(normalized_stem) >= 4 and normalized_stem in normalized_name:
                match_score = 3
            elif len(normalized_name) >= 5 and normalized_name in normalized_stem:
                match_score = 2
            elif normalized_stem in identity_words:
                match_score = 2
            elif stem_words & identity_words:
                # Product displays commonly add channel/version decorations
                # ("Organteq Trial version 2.1.2") that are absent from the
                # actual executable ("Organteq 2.exe"). A distinctive shared
                # word is useful only after installer/uninstaller binaries
                # have been removed from consideration.
                match_score = 2
            if match_score:
                scored.append(
                    (
                        -match_score,
                        depth,
                        0 if path.suffix.casefold() == ".ico" else 1,
                        len(str(path)),
                        path.name.casefold(),
                        path,
                    )
                )
    if scored:
        ranked = sorted(scored)
        if cached_source_has_windows_placeholder(ranked[0][-1]):
            # A sole valid loose ICO beside this application's executables
            # preserves native high-resolution artwork, not a secondary tray slot.
            icons = [path for path in fallback_files if path.parent == root
                     and path.suffix.casefold() == ".ico" and _local_raster_artwork_extent(path)]
            if len(icons) == 1:
                return icons[0]
        for *_, candidate in ranked:
            if not cached_source_has_windows_placeholder(candidate):
                return candidate
    if desktop_icon is not None:
        return desktop_icon
    # Portable command packages frequently contain one short alias (``fd``,
    # ``rg``) that cannot be inferred safely from their display name. A sole
    # local executable/icon is unambiguous package-bound evidence.
    return (fallback_files[0] if len(fallback_files) == 1
            and not cached_source_has_windows_placeholder(fallback_files[0]) else None)


_WINDOWS_PLACEHOLDER_PIXELS = {
    (16, 16): "bede9ecd44aaf9a1e8c4394cb7a392ad50660b4f0ddf43695b6197363706de68",
    (24, 24): "50305fb71af3a8135ba9c7c527e462c52082f1eb298da0ca0b67ee65f1058c0f",
    (32, 32): "7ea32e0a0243cea4229528c407c176f161841bdbafb10f9baf2f228cb3f11e5e",
    (40, 40): "23e7822e4fa054a538fe8099ecdf680bae6e8273134209658de78124314d6659",
    (48, 48): "d88ebb95749e5a1f925036700942c5f844a97b7a6cab8bff213a264f2412d6f1",
    (64, 64): "5fa4195b6c83a88c9d68162c5987b3def683bca2461cb93a46d3d776dc85e02c",
    (96, 96): "d62df9ff856f24c9b3de478c4430a1aee5a8a89ec25b14c37f4b6e3f1c054366",
    (128, 128): "7168cba3acd14ef438932fe72a98104071a0e17536f8146bbcab5327e5b2f4a6",
    (144, 144): "d51b58e2a19291a39bb48b6bd96fd13f573651eecc22b10c9efa1d03f35c916f",
    (256, 256): "112cf80454b15513407f0ef1ae4addd83c51356fe6fffeb4caf6ccb502772a6c",
}


def windows_placeholder_pixels(width: int, height: int, rows: Sequence[bytes]) -> bool:
    """Match the exact alpha mask and opaque artwork, not unstable edge RGB."""
    expected = _WINDOWS_PLACEHOLDER_PIXELS.get((width, height))
    if not expected or len(rows) != height or any(len(row) != width * 4 for row in rows):
        return False
    raw = bytearray(b"".join(rows))
    # Shell varies fractional-alpha RGB across processes, even for its own
    # generic EXE. Preserve every alpha byte and every fully opaque pixel.
    for offset in range(0, len(raw), 4):
        if raw[offset + 3] != 255:
            raw[offset:offset + 3] = b"\0\0\0"
    return hashlib.sha256(raw).hexdigest() == expected


def known_windows_placeholder(path: Path) -> bool:
    """Exact silhouette/opaque-pixel proof, never general visual resemblance."""
    expected = _WINDOWS_PLACEHOLDER_PIXELS.get(png_dimensions_fast(path))
    if expected and (decoded := read_png_rgba(path)):
        return windows_placeholder_pixels(*decoded)
    return False


def cached_source_has_windows_placeholder(source: Path) -> bool:
    """Reuse source-versioned evidence; do not extract files during discovery."""
    return source.suffix.casefold() == ".exe" and any(
        known_windows_placeholder(source_versioned_raw_icon_cache_path(
            source, size, small_shell_icon=False)) for size in (128, 144)
    )


def likely_uninstaller_icon_source(path: Path) -> bool:
    """Recognize executables whose artwork represents removal, not the app."""

    if path.suffix.casefold() != ".exe":
        return False
    stem = re.sub(r"[\s._-]+", "", path.stem.casefold())
    return bool(
        re.fullmatch(
            r"(?:unins\d*|uninstall(?:er)?\d*|unwise\d*)",
            stem,
        )
    )


def desktop_ini_icon_path(directory: Path) -> Path | None:
    """Resolve a bounded ``desktop.ini`` ``IconResource`` fallback.

    This intentionally reads only the install root and only a small text file;
    icon discovery must never turn into an unbounded shell-folder crawl.
    """

    ini_path = directory / "desktop.ini"
    try:
        if not ini_path.is_file() or ini_path.stat().st_size > 64 * 1024:
            return None
        payload = ini_path.read_bytes()
    except OSError:
        return None
    text = ""
    encodings = (
        ("utf-16",)
        if payload.startswith((b"\xff\xfe", b"\xfe\xff"))
        else ("utf-8-sig", locale.getpreferredencoding(False))
    )
    for encoding in encodings:
        try:
            text = payload.decode(encoding)
            break
        except (LookupError, UnicodeDecodeError):
            continue
    if not text:
        return None
    in_shell_class = False
    resource = ""
    icon_file = ""
    for raw_line in text.splitlines():
        line = raw_line.strip()
        if not line or line.startswith((";", "#")):
            continue
        if line.startswith("[") and line.endswith("]"):
            in_shell_class = line[1:-1].strip().casefold() == ".shellclassinfo"
            continue
        if not in_shell_class or "=" not in line:
            continue
        key, value = (part.strip() for part in line.split("=", 1))
        if key.casefold() == "iconresource":
            resource = value
        elif key.casefold() == "iconfile":
            icon_file = value
    value = resource or icon_file
    if not value:
        return None
    if indirect := resolve_indirect_icon_path(value):
        return indirect
    stripped = strip_display_icon_index(value)
    candidate = Path(os.path.expandvars(stripped.strip().strip('"')))
    if not candidate.is_absolute():
        candidate = directory / candidate
    return candidate if candidate.is_file() else None


_START_MENU_SHORTCUT_INDEX_LOCK = threading.Lock()
_START_MENU_SHORTCUT_INDEX: tuple[
    tuple[Path, str, str, frozenset[str]], ...
] | None = None
_ICON_MATCH_NOISE_WORDS = frozenset(
    {
        "app",
        "application",
        "bit",
        "desktop",
        "for",
        "installer",
        "manager",
        "microsoft",
        "preview",
        "setup",
        "the",
        "tool",
        "tools",
        "user",
        "windows",
        "x64",
        "x86",
    }
)
_PATH_EXECUTABLE_NOISE_WORDS = _ICON_MATCH_NOISE_WORDS | {
    "arp",
    "c++",
    "component",
    "core",
    "framework",
    "machine",
    "msix",
    "package",
    "redistributable",
    "runtime",
    "shared",
    "visual",
}


def invalidate_start_menu_shortcut_index() -> None:
    """Forget shortcut names after package operations may have changed them."""

    global _START_MENU_SHORTCUT_INDEX
    with _START_MENU_SHORTCUT_INDEX_LOCK:
        _START_MENU_SHORTCUT_INDEX = None


def _path_is_windows_app_execution_alias(path: Path) -> bool:
    """Reject per-user Store command aliases when looking for package artwork."""

    local_app_data = os.environ.get("LOCALAPPDATA", "").strip()
    if not local_app_data:
        return False
    alias_root = Path(local_app_data) / "Microsoft" / "WindowsApps"

    def contained(candidate: Path) -> bool:
        try:
            root_text = os.path.normcase(os.path.abspath(alias_root))
            candidate_text = os.path.normcase(os.path.abspath(candidate))
            return os.path.commonpath((root_text, candidate_text)) == root_text
        except (OSError, ValueError):
            return False

    if contained(path):
        return True
    with contextlib.suppress(OSError):
        return contained(path.resolve())
    return False


def _icon_match_text(value: str) -> str:
    return "".join(character.casefold() for character in value if character.isalnum())


def _icon_match_words(value: str) -> set[str]:
    return {
        word
        for word in re.findall(r"[A-Za-z][A-Za-z0-9]{2,}", value.casefold())
        if word not in _ICON_MATCH_NOISE_WORDS
    }


def _shared_shortcut_brand(package_id: str, name: str, package_words: set[str]) -> str:
    """Return a distinctive ecosystem brand safe for a one-word shortcut match."""

    id_parts = [part for part in re.split(r"[\\/._-]+", package_id) if part]
    publisher = _icon_match_text(id_parts[0]) if len(id_parts) > 1 else ""
    name_first = _icon_match_text(name.split(maxsplit=1)[0]) if name.strip() else ""
    # Broad publishers such as Microsoft are deliberately removed from
    # package_words by the noise set. That prevents an unrelated Microsoft
    # shortcut (historically Edge) from branding every runtime component,
    # while a distinctive language ecosystem such as Python remains useful.
    return (
        publisher
        if len(publisher) >= 5 and publisher == name_first and publisher in package_words
        else ""
    )


def _shortcut_prefix_is_distinctive(prefix_length: int, publisher: str) -> bool:
    """Reject a prefix consisting only of a broad package publisher name."""

    return prefix_length >= 8 and (
        not publisher or prefix_length > len(publisher) + 1
    )


def _start_menu_shortcut_index() -> tuple[
    tuple[Path, str, str, frozenset[str]], ...
]:
    """Index local Start Menu shortcut names without resolving their targets.

    Resolution remains delegated to the shell icon worker. Merely enumerating
    local ``.lnk`` names is fast, cannot start an application, and avoids the
    expensive COM work for every unrelated shortcut.
    """

    global _START_MENU_SHORTCUT_INDEX
    with _START_MENU_SHORTCUT_INDEX_LOCK:
        if _START_MENU_SHORTCUT_INDEX is not None:
            return _START_MENU_SHORTCUT_INDEX
        roots = tuple(
            dict.fromkeys(
                Path(value)
                for value in (
                    os.environ.get("APPDATA", "")
                    and str(
                        Path(os.environ["APPDATA"])
                        / "Microsoft"
                        / "Windows"
                        / "Start Menu"
                        / "Programs"
                    ),
                    os.environ.get("PROGRAMDATA", "")
                    and str(
                        Path(os.environ["PROGRAMDATA"])
                        / "Microsoft"
                        / "Windows"
                        / "Start Menu"
                        / "Programs"
                    ),
                )
                if value
            )
        )
        entries: list[tuple[Path, str, str, frozenset[str]]] = []
        for root in roots:
            if not root.is_dir():
                continue
            try:
                for pattern in ("*.lnk", "*.url"):
                    for shortcut in root.rglob(pattern):
                        if len(entries) >= 2500:
                            break
                        with contextlib.suppress(OSError):
                            if shortcut.is_file():
                                relative = shortcut.relative_to(root)
                                entries.append(
                                    (
                                        shortcut,
                                        _icon_match_text(shortcut.stem),
                                        _icon_match_text(" ".join(relative.parts[:-1])),
                                        frozenset(_icon_match_words(shortcut.stem)),
                                    )
                                )
                    if len(entries) >= 2500:
                        break
            except OSError:
                continue
        _START_MENU_SHORTCUT_INDEX = tuple(entries)
        return _START_MENU_SHORTCUT_INDEX


def start_menu_shortcut_icon_path(package_id: str, name: str) -> Path | None:
    """Return a conservatively name-matched local Start Menu shortcut."""

    if os.name != "nt":
        return None
    normalized_name = _icon_match_text(name)
    normalized_id = _icon_match_text(package_id)
    package_words = _icon_match_words(f"{name} {package_id}")
    brand = _shared_shortcut_brand(package_id, name, package_words)
    id_parts = [part for part in re.split(r"[\\/._-]+", package_id) if part]
    publisher = _icon_match_text(id_parts[0]) if len(id_parts) > 1 else ""
    scored: list[tuple[int, int, str, Path]] = []
    for path, shortcut_name, shortcut_parent, shortcut_words in _start_menu_shortcut_index():
        if not shortcut_name:
            continue
        score = 0
        if shortcut_name == normalized_name:
            score = 1200
        elif shortcut_name == normalized_id:
            score = 1150
        elif min(len(shortcut_name), len(normalized_name)) >= 6 and (
            shortcut_name in normalized_name or normalized_name in shortcut_name
        ):
            score = 900 - abs(len(shortcut_name) - len(normalized_name))
        else:
            prefix = len(os.path.commonprefix((shortcut_name, normalized_name)))
            if _shortcut_prefix_is_distinctive(prefix, publisher):
                score = 650 + min(prefix, 30)
            common_words = package_words & shortcut_words
            if len(common_words) >= 2:
                score = max(score, 500 + sum(len(word) for word in common_words))
            elif brand and (shortcut_name.startswith(brand) or brand in shortcut_parent):
                score = max(score, 180)
        if score <= 0:
            continue
        lowered = path.stem.casefold()
        if any(
            word in lowered
            for word in ("manual", "documentation", "docs", "module", "pydoc", "idle")
        ):
            score -= 400
        scored.append((score, -len(path.parts), str(path).casefold(), path))
    return max(scored)[-1] if scored else None


def start_menu_shortcut_launch_path(
    package_id: str,
    name: str,
    *,
    entries: Sequence[tuple[Path, str, str, frozenset[str]]] | None = None,
) -> Path | None:
    """Return one unambiguous, high-confidence Start Menu activation route."""

    paths = start_menu_shortcut_launch_paths(package_id, name, entries=entries)
    return paths[0] if len(paths) == 1 else None


def start_menu_shortcut_launch_paths(
    package_id: str,
    name: str,
    *,
    entries: Sequence[tuple[Path, str, str, frozenset[str]]] | None = None,
) -> tuple[Path, ...]:
    """Keep distinct saved commands; collapse only proven equivalent links."""

    if os.name != "nt" and entries is None:
        return ()
    normalized_name = _icon_match_text(name)
    normalized_id = _icon_match_text(package_id)
    exact: list[Path] = []
    contained: list[Path] = []
    for path, shortcut_name, _shortcut_parent, _shortcut_words in (
        entries if entries is not None else _start_menu_shortcut_index()
    ):
        if path.suffix.casefold() not in {".lnk", ".url"} or not shortcut_name:
            continue
        lowered = path.stem.casefold()
        if any(
            word in lowered
            for word in ("manual", "documentation", "docs", "module", "pydoc", "idle")
        ):
            continue
        if shortcut_name in {normalized_name, normalized_id}:
            exact.append(path)
        elif (
            min(len(shortcut_name), len(normalized_name)) >= 6
            and (shortcut_name in normalized_name or normalized_name in shortcut_name)
        ) or (len(name.strip()) >= 3 and lowered.startswith(name.strip().casefold() + " ")):
            contained.append(path)
    candidates = exact or contained
    unique = {os.path.normcase(os.path.abspath(path)): path for path in candidates}
    commands: dict[tuple[str, ...], Path] = {}
    for path in unique.values():
        signature = ("path", os.path.normcase(os.path.abspath(path)))
        if path.suffix.casefold() == ".lnk":
            with contextlib.suppress(OSError):
                stat = path.stat()
                details = _cached_launch_shortcut(path, stat.st_mtime_ns, stat.st_size)
                if details and details.target and Path(details.target).is_absolute():
                    signature = (
                        "command", os.path.normcase(os.path.normpath(details.target)),
                        details.arguments,
                        os.path.normcase(os.path.normpath(details.working_directory)),
                    )
        commands.setdefault(signature, path)
    return tuple(commands.values())


def path_executable_icon_path(
    package_id: str,
    name: str,
    *,
    primary_id_only: bool = False,
) -> Path | None:
    """Resolve an exact package-derived executable name from the current PATH."""

    if os.name != "nt":
        return None
    # ARP and MSIX inventory IDs encode registry/AppModel namespaces rather
    # than executable names. Treating their components as PATH aliases can
    # bridge ARP -> arp.exe or .NET -> net.exe and then discover unrelated
    # artwork under System32. These rows already have stronger registry,
    # package-root, Start Menu, and Shell evidence paths.
    namespace = package_id.split("\\", 1)[0].casefold()
    if namespace in {"arp", "msix"}:
        return None
    candidates: list[str] = []

    def add(value: str, *, allow_short: bool = False) -> None:
        candidate = re.sub(r"[^A-Za-z0-9_.+-]+", "", value).strip(".")
        minimum_length = 2 if allow_short and candidate.isalpha() else 3
        if (
            minimum_length <= len(candidate) <= 64
            and not candidate[0].isdigit()
            and candidate.casefold() not in _PATH_EXECUTABLE_NOISE_WORDS
            and candidate.casefold() not in {existing.casefold() for existing in candidates}
        ):
            candidates.append(candidate)

    id_parts = [part for part in re.split(r"[\\/._-]+", package_id) if part]
    indexed_id_parts = tuple(enumerate(id_parts))
    if primary_id_only:
        indexed_id_parts = indexed_id_parts[-1:]
    for index, part in reversed(indexed_id_parts):
        # Exact two-letter CLI aliases (go, rg, fd, uv) are common in developer
        # packages. Accept only the package ID's final segment at that length;
        # broad display-name words remain subject to the stricter minimum.
        add(part, allow_short=index == len(id_parts) - 1)
    if not primary_id_only:
        name_words = re.findall(r"[A-Za-z][A-Za-z0-9+_-]*", name)
        for word in name_words[:3]:
            add(word)
    for candidate in candidates[:8]:
        executable_name = candidate if candidate.casefold().endswith(".exe") else candidate + ".exe"
        registered = resolve_registered_app_path(executable_name)
        if registered is not None and not _path_is_windows_app_execution_alias(registered):
            return registered
        resolved = shutil.which(candidate)
        if not resolved and executable_name != candidate:
            resolved = shutil.which(executable_name)
        if not resolved:
            continue
        path = Path(resolved)
        with contextlib.suppress(OSError):
            if (
                not _path_is_windows_app_execution_alias(path)
                and path.is_file()
                and path.suffix.casefold() == ".exe"
            ):
                return path
    return None


def _local_raster_artwork_extent(path: Path) -> int | None:
    """Return the largest native raster edge without asking the Windows shell."""

    if dimensions := png_dimensions_fast(path):
        return max(dimensions)
    try:
        payload = _read_ico_file_bytes(path)
    except OSError:
        return None
    frames = _ico_frames(payload)
    return max((max(frame.width, frame.height) for frame in frames), default=None)


def nearby_install_artwork_path(
    executable: Path,
    current_source: Path,
    package_id: str,
    name: str,
) -> Path | None:
    """Find one stronger loose raster beside a package-derived executable.

    This is deliberately evidence-driven rather than package-specific. It only
    runs when the registered raster is small, searches a bounded local install
    neighborhood, excludes source/test corpora, and accepts an unlabelled image
    only when it is the sole plausible artwork candidate.
    """

    current_extent = _local_raster_artwork_extent(current_source)
    if current_extent is None or not 16 <= current_extent <= 64:
        return None
    try:
        executable = executable.resolve()
        current_source = current_source.resolve()
    except OSError:
        return None
    root = executable.parent
    if root.name.casefold() in {"bin", "cmd", "sbin", "tools"}:
        root = root.parent
    if not root.is_dir():
        return None

    identity_words = {
        normalized_package_name(value)
        for value in re.findall(r"[A-Za-z][A-Za-z0-9+-]{2,}", f"{package_id} {name}")
        if normalized_package_name(value) not in _ICON_MATCH_NOISE_WORDS
    }
    executable_stem = normalized_package_name(executable.stem)
    cue_words = {
        "appicon",
        "artwork",
        "brand",
        "emblem",
        "favicon",
        "icon",
        "logo",
        "mark",
        "mascot",
    }
    skipped_directories = {
        ".git",
        "bench",
        "benchmark",
        "benchmarks",
        "doc",
        "docs",
        "example",
        "examples",
        "node_modules",
        "sample",
        "samples",
        "src",
        "test",
        "testdata",
        "tests",
        "vendor",
    }
    pending: deque[tuple[Path, int]] = deque(((root, 0),))
    candidates: list[tuple[int, int, int, int, int, str, Path]] = []
    visited = 0
    while pending and visited < 1200:
        directory, depth = pending.popleft()
        try:
            # Bound enumeration itself, not just the later candidate loop.
            # Retain DirEntry's metadata after closing the directory handle.
            with os.scandir(directory) as iterator:
                entries = list(itertools.islice(iterator, 1200 - visited))
        except OSError:
            continue
        for entry in entries:
            visited += 1
            try:
                if entry.is_dir():
                    if depth < 4 and entry.name.casefold() not in skipped_directories:
                        pending.append((Path(entry.path), depth + 1))
                    continue
                if not entry.is_file():
                    continue
                path = Path(entry.path)
                if (
                    path.suffix.casefold() not in {".ico", ".png"}
                    or path.resolve() == current_source
                    or entry.stat().st_size > 16 * 1024 * 1024
                ):
                    continue
            except OSError:
                continue
            extent = _local_raster_artwork_extent(path)
            dimensions = png_dimensions_fast(path)
            if extent is None or extent < current_extent or extent > 512:
                continue
            if dimensions is not None:
                width, height = dimensions
                if min(width, height) < 16 or max(width, height) > 2 * min(width, height):
                    continue
                if icon_png_has_visual_detail(path) is not True:
                    continue
            normalized_stem = normalized_package_name(path.stem)
            path_words = {
                normalized_package_name(part)
                for part in path.relative_to(root).parts
            }
            identity_score = 0
            presentation_score = 0
            if normalized_stem in identity_words or normalized_stem == executable_stem:
                identity_score += 120
            if any(word in normalized_stem for word in cue_words):
                presentation_score += 100
            if path_words & cue_words:
                presentation_score += 60
            if any(
                len(word) >= 4 and (word in normalized_stem or normalized_stem in word)
                for word in identity_words
            ):
                identity_score += 40
            candidates.append(
                (
                    identity_score,
                    presentation_score,
                    extent,
                    1 if path.suffix.casefold() == ".png" else 0,
                    -depth,
                    str(path).casefold(),
                    path,
                )
            )
    if not candidates:
        return None
    identity_matched = [candidate for candidate in candidates if candidate[0] > 0]
    eligible = identity_matched or (candidates if len(candidates) == 1 else [])
    if not eligible:
        return None
    best = max(eligible)
    # Equal-sized loose PNGs are allowed to replace small registered ICOs:
    # the PNG can preserve substantially richer color and alpha transitions.
    if (
        best[2] == current_extent
        and current_source.suffix.casefold() == ".png"
        and best[0] == 0
    ):
        return None
    return best[-1]


def higher_quality_nearby_artwork_path(
    current_source: Path,
    package_id: str,
    name: str,
) -> Path | None:
    """Resolve a package executable, then look for stronger adjacent artwork."""

    if _local_raster_artwork_extent(current_source) not in range(16, 65):
        return None
    # A registered icon is already package-bound evidence. Replacing it with
    # loose artwork reached through a publisher/registry namespace word (for
    # example ARP -> Windows' arp.exe) crosses that trust boundary and can
    # brand an unrelated package with arbitrary system artwork. Only the
    # package ID's primary/final executable token may seed this refinement.
    executable = path_executable_icon_path(package_id, name, primary_id_only=True)
    if executable is None:
        return None
    return nearby_install_artwork_path(executable, current_source, package_id, name)


def local_toolchain_brand_icon_path(package_id: str, name: str) -> Path | None:
    """Return authoritative branding shipped with a local developer toolchain."""

    identity = normalized_package_name(f"{package_id} {name}")
    if "rustup" in identity:
        rustup_home = Path(
            os.path.expandvars(os.environ.get("RUSTUP_HOME", str(Path.home() / ".rustup")))
        )
        toolchains = rustup_home / "toolchains"
        if toolchains.is_dir():
            try:
                roots = sorted(
                    (path for path in toolchains.iterdir() if path.is_dir()),
                    key=lambda path: (
                        0 if path.name.casefold().startswith("stable-") else 1,
                        path.name,
                    ),
                )[:16]
            except OSError:
                roots = []
            for root in roots:
                docs = root / "share" / "doc" / "rust" / "html"
                direct = docs / "favicon-32x32.png"
                if direct.is_file() and icon_png_has_visual_detail(direct) is not False:
                    return direct
                static_files = docs / "static.files"
                with contextlib.suppress(OSError):
                    for candidate in sorted(static_files.glob("favicon-32x32-*.png")):
                        if (
                            candidate.is_file()
                            and icon_png_has_visual_detail(candidate) is not False
                        ):
                            return candidate

    package_id_folded = package_id.casefold()
    name_folded = name.casefold()
    if package_id_folded.startswith(
        (
            "microsoft.dotnet.runtime.",
            "microsoft.dotnet.aspnetcore.",
            "microsoft.dotnet.desktopruntime.",
        )
    ) or any(
        marker in name_folded
        for marker in (".net runtime", "asp.net core", "windows desktop runtime")
    ):
        dotnet_roots = [
            value
            for value in (
                os.environ.get("DOTNET_ROOT", ""),
                os.environ.get("DOTNET_ROOT_X64", ""),
                str(Path(os.environ.get("ProgramFiles", r"C:\Program Files")) / "dotnet"),
                str(
                    Path(os.environ.get("ProgramFiles(x86)", r"C:\Program Files (x86)"))
                    / "dotnet"
                ),
            )
            if value
        ]
        for root in dict.fromkeys(dotnet_roots):
            candidate = Path(os.path.expandvars(root)) / "dotnet.exe"
            if candidate.is_file():
                return candidate

    if package_id_folded == "microsoft.visualstudio.locator" or "visual studio locator" in name_folded:
        visual_studio_roots = tuple(
            dict.fromkeys(
                Path(base) / "Microsoft Visual Studio"
                for base in (
                    os.environ.get("ProgramFiles", r"C:\Program Files"),
                    os.environ.get("ProgramFiles(x86)", r"C:\Program Files (x86)"),
                )
                if base
            )
        )
        for visual_studio_root in visual_studio_roots:
            if not visual_studio_root.is_dir():
                continue
            with contextlib.suppress(OSError):
                versions = sorted(
                    (path for path in visual_studio_root.iterdir() if path.is_dir()),
                    reverse=True,
                )[:8]
                for version in versions:
                    editions = sorted(
                        (path for path in version.iterdir() if path.is_dir()),
                        reverse=True,
                    )[:12]
                    for edition in editions:
                        candidate = edition / "Common7" / "IDE" / "devenv.ico"
                        if candidate.is_file():
                            return candidate
    return None


def registered_brand_icon_path(provider: str, package_id: str, icon_source: str) -> Path | None:
    """Known registered uninstallers carry genuine product artwork; never launch them."""
    identity = package_id.casefold()
    supported = identity == "llvm.llvm" or re.fullmatch(
        r'arp\\(?:machine|user)\\(?:x86|x64)\\mozillamaintenanceservice', identity
    )
    if provider == "winget" and supported and icon_source:
        source = Path(strip_display_icon_index(icon_source))
        if source.name.casefold() == "uninstall.exe" and source.is_file():
            return source
    return None


def preferred_installed_shell_icon(provider: str, package_id: str, installed_location: str) -> Path | None:
    """Human-selected shell artwork, bounded to the game's registered install root."""
    match = STEAM_ARP_PACKAGE_ID_RE.fullmatch(package_id) if provider == 'winget' else None
    if not match or not installed_location:
        return None
    executable = _STEAM_SHELL_ICON_EXECUTABLES.get(package_id.rsplit(' ', 1)[-1])
    if executable:
        candidate = Path(installed_location) / executable
        if candidate.is_file():
            return candidate
    return None


def resolve_icon_source_fields(
    provider: str,
    icon_source: str,
    package_id: str,
    installed_location: str,
    name: str,
    target_size: int = 256,
) -> Path | None:
    """Resolve an icon source from boundary fields without mutable GUI state."""
    icon_directory = ""
    if preferred := preferred_installed_shell_icon(provider, package_id, installed_location):
        return preferred
    # Store inventory's Properties/Logo is a logical asset, often a tiny base
    # PNG. Resolve the exact package's qualified manifest artwork before it.
    explicit_appx = provider.casefold() == MICROSOFT_STORE_PROVIDER_KEY and package_id.casefold().startswith("msix\\")
    if explicit_appx:
        if appx_logo := appx_manifest_logo_path(package_id, target_size, name):
            return appx_logo
    if branding := registered_brand_icon_path(provider, package_id, icon_source):
        return branding
    # A few developer ecosystems ship stronger shared branding than their
    # package registration (which is commonly a console shim or uninstaller).
    # This resolver is deliberately narrow, local-only, and bounded.
    if provider.casefold() == "winget":
        if toolchain_icon := local_toolchain_brand_icon_path(package_id, name):
            return toolchain_icon
    if icon_source:
        if indirect := resolve_indirect_icon_path(icon_source):
            if likely_uninstaller_icon_source(indirect) or cached_source_has_windows_placeholder(indirect):
                icon_directory = str(indirect.parent)
            else:
                return (
                    higher_quality_nearby_artwork_path(indirect, package_id, name)
                    if provider.casefold() == "winget"
                    else None
                ) or indirect
        expanded_source = Path(os.path.expandvars(icon_source.strip().strip('"')))
        if expanded_source.is_dir():
            icon_directory = str(expanded_source)
        candidate = Path(strip_display_icon_index(icon_source))
        if candidate.is_file():
            if likely_uninstaller_icon_source(candidate) or cached_source_has_windows_placeholder(candidate):
                icon_directory = str(candidate.parent)
            else:
                return (
                    higher_quality_nearby_artwork_path(candidate, package_id, name)
                    if provider.casefold() == "winget"
                    else None
                ) or candidate
        if registered := resolve_registered_app_path(str(candidate)):
            return registered
    # Fuzzy AppX identity matching is useful for WinGet inventory rows whose
    # IDs may be ARP aliases, but it must never cross provider boundaries.
    # A pip package named ``filelock``, for example, is unrelated to the
    # installed PowerToys File Locksmith AppX component.
    if not explicit_appx and provider.casefold() in {"winget", MICROSOFT_STORE_PROVIDER_KEY}:
        appx_logo = appx_manifest_logo_path(package_id, target_size, name)
        if appx_logo is not None:
            return appx_logo
    installed_icon = install_location_icon_path(
        installed_location or icon_directory,
        name,
        package_id,
    )
    if installed_icon is not None:
        return installed_icon
    if provider.casefold() == "winget":
        if shortcut := start_menu_shortcut_icon_path(package_id, name):
            return shortcut
        if executable := path_executable_icon_path(package_id, name):
            return executable
    return None


def resolve_item_icon_source_path(item: UpdateItem, target_size: int = 256) -> Path | None:
    """Resolve a package's best local icon source without mutating GUI state."""
    return resolve_icon_source_fields(
        item.provider,
        item.icon_source,
        item.package_id,
        item.installed_location,
        item.name,
        target_size,
    )


def item_icon_identity(item: UpdateItem) -> tuple[str, str, str, str, str]:
    """Fields that must remain stable before a decoded icon may survive a rescan."""

    return (
        item.provider,
        item.package_id,
        item.name,
        item.icon_source,
        item.installed_location,
    )


# ==================== Native icon extraction ====================

class GdiplusStartupInput(ctypes.Structure):
    _fields_ = [
        ("GdiplusVersion", ctypes.c_uint32),
        ("DebugEventCallback", ctypes.c_void_p),
        ("SuppressBackgroundThread", ctypes.c_int),
        ("SuppressExternalCodecs", ctypes.c_int),
    ]


class SHFILEINFOW(ctypes.Structure):
    _fields_ = [
        ("hIcon", ctypes.c_void_p),
        ("iIcon", ctypes.c_int),
        ("dwAttributes", ctypes.c_uint32),
        ("szDisplayName", ctypes.c_wchar * 260),
        ("szTypeName", ctypes.c_wchar * 80),
    ]


class ICONINFO(ctypes.Structure):
    _fields_ = [
        ("fIcon", ctypes.c_int),
        ("xHotspot", ctypes.c_uint32),
        ("yHotspot", ctypes.c_uint32),
        ("hbmMask", ctypes.c_void_p),
        ("hbmColor", ctypes.c_void_p),
    ]


class BITMAP(ctypes.Structure):
    _fields_ = [
        ("bmType", ctypes.c_long),
        ("bmWidth", ctypes.c_long),
        ("bmHeight", ctypes.c_long),
        ("bmWidthBytes", ctypes.c_long),
        ("bmPlanes", ctypes.c_ushort),
        ("bmBitsPixel", ctypes.c_ushort),
        ("bmBits", ctypes.c_void_p),
    ]


class BITMAPINFOHEADER(ctypes.Structure):
    _fields_ = [
        ("biSize", ctypes.c_uint32),
        ("biWidth", ctypes.c_long),
        ("biHeight", ctypes.c_long),
        ("biPlanes", ctypes.c_ushort),
        ("biBitCount", ctypes.c_ushort),
        ("biCompression", ctypes.c_uint32),
        ("biSizeImage", ctypes.c_uint32),
        ("biXPelsPerMeter", ctypes.c_long),
        ("biYPelsPerMeter", ctypes.c_long),
        ("biClrUsed", ctypes.c_uint32),
        ("biClrImportant", ctypes.c_uint32),
    ]


class RGBQUAD(ctypes.Structure):
    _fields_ = [
        ("rgbBlue", ctypes.c_ubyte),
        ("rgbGreen", ctypes.c_ubyte),
        ("rgbRed", ctypes.c_ubyte),
        ("rgbReserved", ctypes.c_ubyte),
    ]


class BITMAPINFO_MONO(ctypes.Structure):
    _fields_ = [
        ("bmiHeader", BITMAPINFOHEADER),
        ("bmiColors", RGBQUAD * 2),
    ]


class SIZE(ctypes.Structure):
    _fields_ = [("cx", ctypes.c_long), ("cy", ctypes.c_long)]


PNG_ENCODER_CLSID = uuid.UUID("{557cf406-1a04-11d3-9a73-0000f81ef32e}")
PNG_SIGNATURE = b"\x89PNG\r\n\x1a\n"
SHGFI_ICON = 0x000000100
SHGFI_SMALLICON = 0x000000001
SHGFI_USEFILEATTRIBUTES = 0x000000010
FILE_ATTRIBUTE_NORMAL = 0x00000080
LOAD_LIBRARY_AS_DATAFILE = 0x00000002
RT_ICON = 3
RT_GROUP_ICON = 14
BI_RGB = 0
DIB_RGB_COLORS = 0
SIIGBF_BIGGERSIZEOK = 0x00000001
SIIGBF_ICONONLY = 0x00000004
ISHELLITEMIMAGEFACTORY_IID = uuid.UUID("{bcc18b79-ba16-442f-80c4-8a59c30c463b}")


def _guid_to_ctypes(guid: uuid.UUID) -> ctypes.c_byte * 16:
    return (ctypes.c_byte * 16).from_buffer_copy(guid.bytes_le)


_GDIPLUS_LOCK = threading.Lock()
_GDIPLUS_DLL: Any | None = None
_GDIPLUS_TOKEN: ctypes.c_void_p | None = None


def _gdiplus() -> Any:
    """Start and bind one process-wide GDI+ instance in the renderer child."""

    global _GDIPLUS_DLL, _GDIPLUS_TOKEN
    with _GDIPLUS_LOCK:
        if _GDIPLUS_DLL is not None and _GDIPLUS_TOKEN:
            return _GDIPLUS_DLL
        if os.name != "nt":
            raise OSError("GDI+ is only available on Windows")
        gdiplus = ctypes.WinDLL("gdiplus", use_last_error=True)
        gdiplus.GdiplusStartup.argtypes = [
            ctypes.POINTER(ctypes.c_void_p),
            ctypes.POINTER(GdiplusStartupInput),
            ctypes.c_void_p,
        ]
        gdiplus.GdiplusStartup.restype = ctypes.c_int
        gdiplus.GdipLoadImageFromFile.argtypes = [
            ctypes.c_wchar_p,
            ctypes.POINTER(ctypes.c_void_p),
        ]
        gdiplus.GdipLoadImageFromFile.restype = ctypes.c_int
        gdiplus.GdipCreateBitmapFromHICON.argtypes = [
            ctypes.c_void_p,
            ctypes.POINTER(ctypes.c_void_p),
        ]
        gdiplus.GdipCreateBitmapFromHICON.restype = ctypes.c_int
        gdiplus.GdipSaveImageToFile.argtypes = [
            ctypes.c_void_p,
            ctypes.c_wchar_p,
            ctypes.c_void_p,
            ctypes.c_void_p,
        ]
        gdiplus.GdipSaveImageToFile.restype = ctypes.c_int
        gdiplus.GdipSaveImageToStream.argtypes = [
            ctypes.c_void_p,
            ctypes.c_void_p,
            ctypes.c_void_p,
            ctypes.c_void_p,
        ]
        gdiplus.GdipSaveImageToStream.restype = ctypes.c_int
        gdiplus.GdipDisposeImage.argtypes = [ctypes.c_void_p]
        gdiplus.GdipDisposeImage.restype = ctypes.c_int
        gdiplus.GdiplusShutdown.argtypes = [ctypes.c_void_p]
        gdiplus.GdiplusShutdown.restype = None
        token = ctypes.c_void_p()
        startup = GdiplusStartupInput(1, None, False, False)
        if gdiplus.GdiplusStartup(ctypes.byref(token), ctypes.byref(startup), None) != 0:
            raise OSError("GdiplusStartup failed")
        _GDIPLUS_DLL = gdiplus
        _GDIPLUS_TOKEN = token
        return gdiplus


def _shutdown_gdiplus() -> None:
    global _GDIPLUS_DLL, _GDIPLUS_TOKEN
    with _GDIPLUS_LOCK:
        gdiplus, token = _GDIPLUS_DLL, _GDIPLUS_TOKEN
        _GDIPLUS_DLL = None
        _GDIPLUS_TOKEN = None
    if gdiplus is not None and token:
        with contextlib.suppress(Exception):
            gdiplus.GdiplusShutdown(token)


atexit.register(_shutdown_gdiplus)


@functools.cache
def _icon_gdi32() -> Any:
    """Return the icon worker's GDI bindings with signatures installed once."""

    gdi32 = ctypes.WinDLL("gdi32", use_last_error=True)
    gdi32.GetObjectW.argtypes = [ctypes.c_void_p, ctypes.c_int, ctypes.c_void_p]
    gdi32.GetObjectW.restype = ctypes.c_int
    gdi32.GetDIBits.argtypes = [
        ctypes.c_void_p,
        ctypes.c_void_p,
        ctypes.c_uint,
        ctypes.c_uint,
        ctypes.c_void_p,
        ctypes.c_void_p,
        ctypes.c_uint,
    ]
    gdi32.GetDIBits.restype = ctypes.c_int
    gdi32.DeleteObject.argtypes = [ctypes.c_void_p]
    gdi32.DeleteObject.restype = ctypes.c_int
    return gdi32


@functools.cache
def _icon_user32() -> Any:
    """Return the icon worker's User32 bindings with signatures installed once."""

    user32 = _user32()
    user32.GetDC.argtypes = [ctypes.c_void_p]
    user32.GetDC.restype = ctypes.c_void_p
    user32.ReleaseDC.argtypes = [ctypes.c_void_p, ctypes.c_void_p]
    user32.ReleaseDC.restype = ctypes.c_int
    user32.GetIconInfo.argtypes = [ctypes.c_void_p, ctypes.POINTER(ICONINFO)]
    user32.GetIconInfo.restype = ctypes.c_int
    user32.DestroyIcon.argtypes = [ctypes.c_void_p]
    user32.DestroyIcon.restype = ctypes.c_int
    with contextlib.suppress(AttributeError):
        user32.PrivateExtractIconsW.argtypes = [
            ctypes.c_wchar_p,
            ctypes.c_int,
            ctypes.c_int,
            ctypes.c_int,
            ctypes.POINTER(ctypes.c_void_p),
            ctypes.POINTER(ctypes.c_uint),
            ctypes.c_uint,
            ctypes.c_uint,
        ]
        user32.PrivateExtractIconsW.restype = ctypes.c_uint
    return user32


@functools.cache
def _icon_shell32() -> Any:
    """Return the small Shell API surface used by icon discovery."""

    shell32 = ctypes.WinDLL("shell32", use_last_error=True)
    shell32.SHGetFileInfoW.argtypes = [
        ctypes.c_wchar_p,
        ctypes.c_uint32,
        ctypes.POINTER(SHFILEINFOW),
        ctypes.c_uint32,
        ctypes.c_uint32,
    ]
    shell32.SHGetFileInfoW.restype = ctypes.c_size_t
    with contextlib.suppress(AttributeError):
        shell32.SHDefExtractIconW.argtypes = [
            ctypes.c_wchar_p,
            ctypes.c_int,
            ctypes.c_uint32,
            ctypes.POINTER(ctypes.c_void_p),
            ctypes.POINTER(ctypes.c_void_p),
            ctypes.c_uint32,
        ]
        shell32.SHDefExtractIconW.restype = ctypes.c_long
    with contextlib.suppress(AttributeError):
        shell32.SHCreateItemFromParsingName.argtypes = [
            ctypes.c_wchar_p,
            ctypes.c_void_p,
            ctypes.c_void_p,
            ctypes.POINTER(ctypes.c_void_p),
        ]
        shell32.SHCreateItemFromParsingName.restype = ctypes.c_long
    return shell32


@functools.cache
def _icon_ole32() -> Any:
    ole32 = ctypes.WinDLL("ole32", use_last_error=True)
    ole32.CreateStreamOnHGlobal.argtypes = [
        ctypes.c_void_p,
        ctypes.c_int,
        ctypes.POINTER(ctypes.c_void_p),
    ]
    ole32.CreateStreamOnHGlobal.restype = ctypes.c_long
    ole32.GetHGlobalFromStream.argtypes = [ctypes.c_void_p, ctypes.POINTER(ctypes.c_void_p)]
    ole32.GetHGlobalFromStream.restype = ctypes.c_long
    return ole32


@functools.cache
def _icon_kernel32() -> Any:
    kernel32 = ctypes.WinDLL("kernel32", use_last_error=True)
    kernel32.GlobalSize.argtypes = [ctypes.c_void_p]
    kernel32.GlobalSize.restype = ctypes.c_size_t
    kernel32.GlobalLock.argtypes = [ctypes.c_void_p]
    kernel32.GlobalLock.restype = ctypes.c_void_p
    kernel32.GlobalUnlock.argtypes = [ctypes.c_void_p]
    kernel32.GlobalUnlock.restype = ctypes.c_int
    return kernel32


def _hbitmap_rgba_rows(hbitmap: int) -> tuple[int, int, list[bytes]] | None:
    """Read a Windows bitmap as top-down RGBA without asking GDI+ to rebuild alpha."""

    if os.name != "nt" or not hbitmap:
        return None
    gdi32 = _icon_gdi32()
    user32 = _icon_user32()

    bitmap = BITMAP()
    if not gdi32.GetObjectW(hbitmap, ctypes.sizeof(bitmap), ctypes.byref(bitmap)):
        return None
    width, height = abs(int(bitmap.bmWidth)), abs(int(bitmap.bmHeight))
    if not width or not height or width * height > MAX_ICON_DECODE_PIXELS:
        return None
    header = BITMAPINFOHEADER(
        ctypes.sizeof(BITMAPINFOHEADER),
        width,
        -height,  # Negative height requests top-down scan lines.
        1,
        32,
        BI_RGB,
        width * height * 4,
        0,
        0,
        0,
        0,
    )
    buffer = (ctypes.c_ubyte * (width * height * 4))()
    dc = user32.GetDC(None)
    if not dc:
        return None
    try:
        copied = int(
            gdi32.GetDIBits(
                dc,
                hbitmap,
                0,
                height,
                buffer,
                ctypes.byref(header),
                DIB_RGB_COLORS,
            )
        )
    finally:
        user32.ReleaseDC(None, dc)
    if copied != height:
        return None
    raw = bytes(buffer)
    rows: list[bytes] = []
    stride = width * 4
    for y in range(height):
        bgra = raw[y * stride : (y + 1) * stride]
        rgba = bytearray(stride)
        rgba[0::4] = bgra[2::4]
        rgba[1::4] = bgra[1::4]
        rgba[2::4] = bgra[0::4]
        rgba[3::4] = bgra[3::4]
        rows.append(bytes(rgba))
    return width, height, rows


def _hbitmap_mask_rows(hbitmap: int, width: int, height: int) -> list[bytes] | None:
    """Read an HICON's monochrome AND mask as top-down packed scan lines."""

    if os.name != "nt" or not hbitmap or width <= 0 or height <= 0:
        return None
    gdi32 = _icon_gdi32()
    user32 = _icon_user32()
    stride = ((width + 31) // 32) * 4
    info = BITMAPINFO_MONO()
    info.bmiHeader = BITMAPINFOHEADER(
        ctypes.sizeof(BITMAPINFOHEADER),
        width,
        height,  # Positive height yields a bottom-up DIB; reverse below.
        1,
        1,
        BI_RGB,
        stride * height,
        0,
        0,
        2,
        2,
    )
    info.bmiColors[0] = RGBQUAD(0, 0, 0, 0)
    info.bmiColors[1] = RGBQUAD(255, 255, 255, 0)
    buffer = (ctypes.c_ubyte * (stride * height))()
    dc = user32.GetDC(None)
    if not dc:
        return None
    try:
        copied = int(
            gdi32.GetDIBits(
                dc,
                hbitmap,
                0,
                height,
                buffer,
                ctypes.byref(info),
                DIB_RGB_COLORS,
            )
        )
    finally:
        user32.ReleaseDC(None, dc)
    if copied != height:
        return None
    raw = bytes(buffer)
    return [
        raw[(height - 1 - y) * stride : (height - y) * stride]
        for y in range(height)
    ]


def _hbitmap_png_bytes(hbitmap: int) -> bytes | None:
    decoded = _hbitmap_rgba_rows(hbitmap)
    if decoded is None:
        return None
    width, height, rows = decoded
    # Shell image factories promise ARGB. Treat an all-zero alpha plane as an
    # unusable response so callers can continue to the established fallbacks.
    if not any(row[3::4].strip(b"\0") for row in rows):
        return None
    return rgba_png_bytes(width, height, rows)


def _save_hbitmap_to_png(hbitmap: int, destination: Path) -> bool:
    payload = _hbitmap_png_bytes(hbitmap)
    if payload is None:
        return False
    destination.parent.mkdir(parents=True, exist_ok=True)
    destination.write_bytes(payload)
    return True


def _hicon_png_bytes_legacy(hicon: int) -> bytes | None:
    """Encode unusual monochrome HICONs through a COM memory stream."""

    gdiplus = _gdiplus()
    bitmap = ctypes.c_void_p()
    stream = ctypes.c_void_p()
    try:
        if gdiplus.GdipCreateBitmapFromHICON(ctypes.c_void_p(hicon), ctypes.byref(bitmap)) != 0:
            return None
        ole32 = _icon_ole32()
        kernel32 = _icon_kernel32()
        if ole32.CreateStreamOnHGlobal(None, True, ctypes.byref(stream)) < 0 or not stream:
            return None
        encoder = _guid_to_ctypes(PNG_ENCODER_CLSID)
        if gdiplus.GdipSaveImageToStream(bitmap, stream, ctypes.byref(encoder), None) != 0:
            return None
        global_handle = ctypes.c_void_p()
        if ole32.GetHGlobalFromStream(stream, ctypes.byref(global_handle)) < 0:
            return None
        size = int(kernel32.GlobalSize(global_handle))
        if not 0 < size <= 32 * 1024 * 1024:
            return None
        pointer = kernel32.GlobalLock(global_handle)
        if not pointer:
            return None
        try:
            return ctypes.string_at(pointer, size)
        finally:
            kernel32.GlobalUnlock(global_handle)
    finally:
        if stream:
            with contextlib.suppress(Exception):
                vtable = ctypes.cast(
                    stream, ctypes.POINTER(ctypes.POINTER(ctypes.c_void_p))
                ).contents
                release = ctypes.WINFUNCTYPE(ctypes.c_ulong, ctypes.c_void_p)(vtable[2])
                release(stream)
        if bitmap:
            with contextlib.suppress(Exception):
                gdiplus.GdipDisposeImage(bitmap)


def _hicon_png_bytes(hicon: int) -> bytes | None:
    """Preserve modern HICON alpha and return a PNG without filesystem I/O."""

    if os.name != "nt" or not hicon:
        return None
    user32 = _icon_user32()
    gdi32 = _icon_gdi32()
    info = ICONINFO()
    if not user32.GetIconInfo(hicon, ctypes.byref(info)):
        return _hicon_png_bytes_legacy(hicon)
    try:
        if not info.hbmColor:
            return _hicon_png_bytes_legacy(hicon)
        decoded = _hbitmap_rgba_rows(info.hbmColor)
        if decoded is None:
            return _hicon_png_bytes_legacy(hicon)
        width, height, rows = decoded
        if not any(row[3::4].strip(b"\0") for row in rows):
            mask_rows = _hbitmap_mask_rows(info.hbmMask, width, height)
            if mask_rows is None:
                return _hicon_png_bytes_legacy(hicon)
            rebuilt: list[bytes] = []
            for rgba_row, mask_row in zip(rows, mask_rows, strict=True):
                row = bytearray(rgba_row)
                # An AND-mask bit of 1 means transparent. Expand eight pixels
                # per Python iteration, then let strided assignment run in C.
                alpha = b"".join(
                    AND_MASK_ALPHA_BYTES[value]
                    for value in mask_row[: (width + 7) // 8]
                )[:width]
                row[3::4] = alpha
                rebuilt.append(bytes(row))
            rows = rebuilt
        return rgba_png_bytes(width, height, rows)
    except OSError:
        return _hicon_png_bytes_legacy(hicon)
    finally:
        for bitmap in (info.hbmColor, info.hbmMask):
            if bitmap:
                with contextlib.suppress(Exception):
                    gdi32.DeleteObject(bitmap)


def _save_hicon_to_png(hicon: int, destination: Path) -> bool:
    payload = _hicon_png_bytes(hicon)
    if payload is None:
        return False
    destination.parent.mkdir(parents=True, exist_ok=True)
    destination.write_bytes(payload)
    return True


def normalize_image_png_with_gdiplus(source: Path, destination: Path) -> bool:
    """Normalize a Windows-readable image into a non-interlaced PNG."""
    if os.name != "nt" or not source.exists():
        return False
    try:
        gdiplus = _gdiplus()
    except OSError:
        return False
    image = ctypes.c_void_p()
    try:
        if gdiplus.GdipLoadImageFromFile(str(source), ctypes.byref(image)) != 0:
            return False
        destination.parent.mkdir(parents=True, exist_ok=True)
        encoder = _guid_to_ctypes(PNG_ENCODER_CLSID)
        return (
            gdiplus.GdipSaveImageToFile(
                image,
                str(destination),
                ctypes.byref(encoder),
                None,
            )
            == 0
        )
    finally:
        if image:
            with contextlib.suppress(Exception):
                gdiplus.GdipDisposeImage(image)


def _icon_frame_score(
    width: int,
    height: int,
    bit_count: int,
    byte_size: int,
    target_size: int,
) -> tuple[int, int, int, int, int]:
    physical = max(width, height)
    area = width * height
    meets_target = 1 if physical >= target_size else 0
    size_rank = -physical if meets_target else physical
    area_rank = -area if meets_target else area
    return meets_target, size_rank, area_rank, bit_count, byte_size


@dataclasses.dataclass(frozen=True, slots=True)
class IcoFrame:
    width: int
    height: int
    bit_count: int
    byte_size: int
    image_offset: int


def _read_ico_file_bytes(source: Path) -> bytes:
    """Bound a single opened file; reject size drift instead of reading without a limit."""

    with source.open("rb") as stream:
        size = os.fstat(stream.fileno()).st_size
        if not 6 <= size <= MAX_ICO_FILE_BYTES:
            return b""
        # Size the read to this file, not the 64 MiB limit, so small icons do
        # not cause a large temporary allocation. The extra byte detects growth.
        data = stream.read(size + 1)
    return data if len(data) == size else b""


def _ico_frames(data: bytes) -> tuple[IcoFrame, ...]:
    """Parse bounded ICO descriptors without retaining or copying frame payloads."""

    if not 6 <= len(data) <= MAX_ICO_FILE_BYTES:
        return ()
    reserved, icon_type, count = struct.unpack_from("<HHH", data, 0)
    if reserved != 0 or icon_type != 1 or not 0 < count <= 512:
        return ()
    if 6 + count * 16 > len(data):
        return ()
    frames: list[IcoFrame] = []
    for index in range(count):
        offset = 6 + index * 16
        width_raw, height_raw, _colors, _reserved, _planes, bit_count, size, image_offset = (
            struct.unpack_from("<BBBBHHII", data, offset)
        )
        width = 256 if width_raw == 0 else width_raw
        height = 256 if height_raw == 0 else height_raw
        if size <= 0 or image_offset < 6 + count * 16 or image_offset + size > len(data):
            continue
        frames.append(
            IcoFrame(
                width,
                height,
                bit_count,
                size,
                image_offset,
            )
        )
    return tuple(frames)


def _best_ico_frame(data: bytes, target_size: int) -> IcoFrame | None:
    return max(
        _ico_frames(data),
        key=lambda frame: _icon_frame_score(
            frame.width,
            frame.height,
            frame.bit_count,
            frame.byte_size,
            target_size,
        ),
        default=None,
    )


def standalone_ico_native_frame_size(source: Path, target_size: int) -> tuple[int, int] | None:
    """Return the real standalone-ICO frame Windows should extract without rescaling."""

    try:
        if source.suffix.casefold() != ".ico":
            with source.open("rb") as stream:
                if stream.read(4) != b"\x00\x00\x01\x00":
                    return None
        frame = _best_ico_frame(_read_ico_file_bytes(source), target_size)
    except OSError:
        return None
    return (frame.width, frame.height) if frame is not None else None


def _best_png_frame_from_ico(data: bytes, target_size: int) -> bytes | None:
    best = max(
        (
            frame for frame in _ico_frames(data)
            if data.startswith(PNG_SIGNATURE, frame.image_offset, frame.image_offset + frame.byte_size)
        ),
        key=lambda frame: _icon_frame_score(
            frame.width,
            frame.height,
            frame.bit_count,
            frame.byte_size,
            target_size,
        ),
        default=None,
    )
    return data[best.image_offset : best.image_offset + best.byte_size] if best is not None else None


def extract_embedded_png_icon(
    source: Path,
    destination: Path | None,
    target_size: int,
    *,
    payload_out: list[bytes] | None = None,
) -> bool:
    """Extract the least expensive already-PNG frame suitable for the target.

    This is a narrow, safe Windows-native fast path. If the best icon frame is a
    DIB rather than PNG, callers fall back to Shell/GDI extraction.
    """

    if not source.exists():
        return False

    def emit(payload: bytes) -> bool:
        if payload_out is not None:
            payload_out.append(payload)
        if destination is not None:
            destination.parent.mkdir(parents=True, exist_ok=True)
            destination.write_bytes(payload)
        return True

    suffix = source.suffix.casefold()
    if suffix == ".png":
        return False
    is_ico_payload = suffix == ".ico"
    if not is_ico_payload:
        try:
            with source.open("rb") as stream:
                is_ico_payload = stream.read(4) == b"\x00\x00\x01\x00"
        except OSError:
            return False
    if is_ico_payload:
        try:
            payload = _best_png_frame_from_ico(_read_ico_file_bytes(source), target_size)
        except OSError:
            return False
        if payload is None:
            return False
        return emit(payload)
    if os.name != "nt" or suffix not in {".exe", ".dll"}:
        return False

    kernel32 = ctypes.WinDLL("kernel32", use_last_error=True)
    load_library_ex = kernel32.LoadLibraryExW
    load_library_ex.argtypes = [ctypes.c_wchar_p, ctypes.c_void_p, ctypes.c_uint32]
    load_library_ex.restype = ctypes.c_void_p
    free_library = kernel32.FreeLibrary
    free_library.argtypes = [ctypes.c_void_p]
    free_library.restype = ctypes.c_int
    callback_type = ctypes.WINFUNCTYPE(
        ctypes.c_bool,
        ctypes.c_void_p,
        ctypes.c_void_p,
        ctypes.c_void_p,
        ctypes.c_void_p,
    )
    enum_resource_names = kernel32.EnumResourceNamesW
    enum_resource_names.argtypes = [
        ctypes.c_void_p,
        ctypes.c_void_p,
        callback_type,
        ctypes.c_void_p,
    ]
    enum_resource_names.restype = ctypes.c_int
    find_resource = kernel32.FindResourceW
    find_resource.argtypes = [ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p]
    find_resource.restype = ctypes.c_void_p
    load_resource = kernel32.LoadResource
    load_resource.argtypes = [ctypes.c_void_p, ctypes.c_void_p]
    load_resource.restype = ctypes.c_void_p
    lock_resource = kernel32.LockResource
    lock_resource.argtypes = [ctypes.c_void_p]
    lock_resource.restype = ctypes.c_void_p
    sizeof_resource = kernel32.SizeofResource
    sizeof_resource.argtypes = [ctypes.c_void_p, ctypes.c_void_p]
    sizeof_resource.restype = ctypes.c_uint32

    module = load_library_ex(str(source), None, LOAD_LIBRARY_AS_DATAFILE)
    if not module:
        return False

    def resource_arg(value: int | str) -> ctypes.c_void_p:
        if isinstance(value, int):
            return ctypes.c_void_p(value)
        return ctypes.cast(ctypes.c_wchar_p(value), ctypes.c_void_p)

    try:
        groups: list[int | str] = []

        def enum_callback(_module: int, _type: int, name: int, _param: int) -> bool:
            pointer = int(name or 0)
            if pointer and pointer <= 0xFFFF:
                groups.append(pointer)
            elif pointer:
                with contextlib.suppress(Exception):
                    groups.append(ctypes.wstring_at(pointer))
            return True

        callback = callback_type(enum_callback)
        enum_resource_names(module, ctypes.c_void_p(RT_GROUP_ICON), callback, None)
        if not groups:
            return False
        best_payload: tuple[tuple[int, int, int, int, int], bytes] | None = None
        # Resources in later groups may be tray/status artwork, not larger
        # renditions of the app icon. Only rank frames within the default group;
        # if it has no PNG frame, the caller asks Windows for its default icon.
        for group in groups[:1]:
            group_resource = find_resource(
                module, resource_arg(group), ctypes.c_void_p(RT_GROUP_ICON)
            )
            if not group_resource:
                continue
            group_handle = load_resource(module, group_resource)
            group_pointer = lock_resource(group_handle)
            group_size = int(sizeof_resource(module, group_resource))
            if not group_pointer or group_size < 6:
                continue
            group_data = ctypes.string_at(group_pointer, group_size)
            _reserved, icon_type, count = struct.unpack_from("<HHH", group_data, 0)
            if icon_type != 1 or count <= 0:
                continue
            for entry_index in range(count):
                offset = 6 + entry_index * 14
                if offset + 14 > len(group_data):
                    break
                (
                    width_raw,
                    height_raw,
                    _colors,
                    _reserved,
                    _planes,
                    bit_count,
                    bytes_in_res,
                    icon_id,
                ) = struct.unpack_from("<BBBBHHIH", group_data, offset)
                icon_resource = find_resource(
                    module, ctypes.c_void_p(icon_id), ctypes.c_void_p(RT_ICON)
                )
                if not icon_resource:
                    continue
                icon_handle = load_resource(module, icon_resource)
                icon_pointer = lock_resource(icon_handle)
                icon_size = int(sizeof_resource(module, icon_resource))
                if not icon_pointer or icon_size <= 0:
                    continue
                payload = ctypes.string_at(icon_pointer, icon_size)
                if not payload.startswith(PNG_SIGNATURE):
                    continue
                width = 256 if width_raw == 0 else width_raw
                height = 256 if height_raw == 0 else height_raw
                score = _icon_frame_score(
                    width,
                    height,
                    bit_count,
                    min(bytes_in_res, icon_size),
                    target_size,
                )
                if best_payload is None or score > best_payload[0]:
                    best_payload = (score, payload)
        if best_payload is None:
            return False
        return emit(best_payload[1])
    finally:
        free_library(module)


def extract_private_icon_png(
    source: Path,
    destination: Path | None,
    target_size: int,
    *,
    method_out: list[str] | None = None,
    payload_out: list[bytes] | None = None,
) -> bool:
    """Ask Windows for a target-sized executable/icon frame before shell fallback."""

    if (
        os.name != "nt"
        or not source.exists()
        or source.suffix.casefold() not in {".exe", ".dll", ".ico"}
    ):
        return False
    user32 = _icon_user32()
    shell32 = _icon_shell32()
    size = max(16, min(256, int(target_size)))

    def capture(hicon_value: int) -> bool:
        if destination is not None:
            return _save_hicon_to_png(hicon_value, destination)
        payload = _hicon_png_bytes(hicon_value)
        if payload is None:
            return False
        if payload_out is not None:
            payload_out.append(payload)
        return True

    # SHDefExtractIconW honors MUI redirection and requests an explicit frame
    # size. It is a documented, conservative improvement over the older
    # PrivateExtractIcons path; retain the latter for systems/files it rejects.
    with contextlib.suppress(AttributeError, OSError):
        shdef_extract = shell32.SHDefExtractIconW
        hicon = ctypes.c_void_p()
        result = int(
            shdef_extract(
                str(source),
                0,
                0,
                ctypes.byref(hicon),
                None,
                size,
            )
        )
        if result >= 0 and hicon.value:
            try:
                if capture(hicon.value):
                    if method_out is not None:
                        method_out.append("SHDefExtractIconW")
                    return True
            finally:
                user32.DestroyIcon(hicon)

    try:
        extract = user32.PrivateExtractIconsW
    except AttributeError:
        return False
    hicon = ctypes.c_void_p()
    icon_id = ctypes.c_uint()
    try:
        extracted = int(
            extract(
                str(source),
                0,
                size,
                size,
                ctypes.byref(hicon),
                ctypes.byref(icon_id),
                1,
                0,
            )
        )
    except OSError:
        return False
    if extracted == 0 or not hicon.value:
        return False
    try:
        try:
            saved = capture(hicon.value)
            if saved and method_out is not None:
                method_out.append("PrivateExtractIconsW")
            return saved
        except OSError:
            return False
    finally:
        with contextlib.suppress(Exception):
            user32.DestroyIcon(hicon)


def extract_shell_item_image_png(
    source: Path,
    destination: Path | None,
    target_size: int,
    *,
    payload_out: list[bytes] | None = None,
) -> bool:
    """Ask the documented Shell image factory for application artwork off the UI thread."""

    if os.name != "nt" or not source.exists():
        return False
    try:
        shell32 = _icon_shell32()
        gdi32 = _icon_gdi32()
        create_item = shell32.SHCreateItemFromParsingName
    except (AttributeError, OSError):
        return False
    factory = ctypes.c_void_p()
    iid = _guid_to_ctypes(ISHELLITEMIMAGEFACTORY_IID)
    try:
        result = int(create_item(str(source), None, ctypes.byref(iid), ctypes.byref(factory)))
    except OSError:
        return False
    if result < 0 or not factory.value:
        return False
    bitmap = ctypes.c_void_p()
    try:
        vtable = ctypes.cast(
            factory,
            ctypes.POINTER(ctypes.POINTER(ctypes.c_void_p)),
        ).contents
        get_image = ctypes.WINFUNCTYPE(
            ctypes.c_long,
            ctypes.c_void_p,
            SIZE,
            ctypes.c_uint32,
            ctypes.POINTER(ctypes.c_void_p),
        )(vtable[3])
        size = max(16, min(512, int(target_size)))
        result = int(
            get_image(
                factory,
                SIZE(size, size),
                SIIGBF_ICONONLY | SIIGBF_BIGGERSIZEOK,
                ctypes.byref(bitmap),
            )
        )
        if result < 0 or not bitmap.value:
            return False
        if destination is not None:
            return _save_hbitmap_to_png(bitmap.value, destination)
        payload = _hbitmap_png_bytes(bitmap.value)
        if payload is None:
            return False
        if payload_out is not None:
            payload_out.append(payload)
        return True
    except (OSError, ValueError):
        return False
    finally:
        if bitmap.value:
            with contextlib.suppress(Exception):
                gdi32.DeleteObject(bitmap)
        with contextlib.suppress(Exception):
            vtable = ctypes.cast(
                factory,
                ctypes.POINTER(ctypes.POINTER(ctypes.c_void_p)),
            ).contents
            release = ctypes.WINFUNCTYPE(ctypes.c_ulong, ctypes.c_void_p)(vtable[2])
            release(factory)


def extract_shell_icon_png(
    source: Path,
    destination: Path | None,
    *,
    small: bool = True,
    payload_out: list[bytes] | None = None,
) -> bool:
    if os.name != "nt" or not source.exists():
        return False
    shell32 = _icon_shell32()
    user32 = _icon_user32()
    info = SHFILEINFOW()
    flags = SHGFI_ICON | (SHGFI_SMALLICON if small else 0)
    result = shell32.SHGetFileInfoW(
        str(source),
        0,
        ctypes.byref(info),
        ctypes.sizeof(info),
        flags,
    )
    if not result or not info.hIcon:
        return False
    try:
        try:
            if destination is not None:
                return _save_hicon_to_png(info.hIcon, destination)
            payload = _hicon_png_bytes(info.hIcon)
            if payload is None:
                return False
            if payload_out is not None:
                payload_out.append(payload)
            return True
        except OSError:
            return False
    finally:
        with contextlib.suppress(Exception):
            user32.DestroyIcon(info.hIcon)


def generic_executable_shell_icon_png_bytes() -> bytes | None:
    """Ask Shell for its generic EXE artwork without creating a dummy file."""

    if os.name != "nt":
        return None
    shell32 = _icon_shell32()
    user32 = _icon_user32()
    info = SHFILEINFOW()
    result = shell32.SHGetFileInfoW(
        "WinDevPilot-generic-placeholder.exe",
        FILE_ATTRIBUTE_NORMAL,
        ctypes.byref(info),
        ctypes.sizeof(info),
        SHGFI_ICON | SHGFI_USEFILEATTRIBUTES,
    )
    if not result or not info.hIcon:
        return None
    try:
        return _hicon_png_bytes(info.hIcon)
    finally:
        with contextlib.suppress(Exception):
            user32.DestroyIcon(info.hIcon)


def materialize_icon_source_png(
    source: Path,
    destination: Path,
    *,
    small_shell_icon: bool,
    target_size: int,
) -> bool:
    """Atomically materialize one source as a raw PNG cache entry."""
    # Tiny executable icon groups sometimes contain a deliberately simplified
    # notification/tray glyph that is not the application's recognizable icon
    # (Notepad++ ships a gray ring at 40px beside its normal 256px artwork).
    # For list presentation, ask for at least a medium resource and downsample
    # it later. This retains crisp pixels without mistaking a secondary glyph
    # for the package identity.
    extraction_target = max(128, target_size) if small_shell_icon else target_size
    native_ico_size = (
        standalone_ico_native_frame_size(source, extraction_target) if source.exists() else None
    )
    native_extraction_target = max(native_ico_size) if native_ico_size is not None else None
    if destination.exists():
        try:
            if destination.stat().st_size > len(PNG_SIGNATURE):
                with destination.open("rb") as stream:
                    valid_png = stream.read(len(PNG_SIGNATURE)) == PNG_SIGNATURE
                cached_size = png_dimensions_fast(destination) if valid_png else None
                native_size_matches = (
                    native_ico_size is None
                    or cached_size == native_ico_size
                    or cached_size == (native_extraction_target, native_extraction_target)
                )
                if valid_png and native_size_matches:
                    return True
        except OSError:
            pass
    if not source.exists():
        return False
    destination.parent.mkdir(parents=True, exist_ok=True)
    temporary = destination.with_name(
        f".{destination.name}.{os.getpid()}.{threading.get_ident()}.raw.png"
    )
    try:
        if source.suffix.casefold() == ".png":
            shutil.copyfile(source, temporary)
            produced = True
        else:
            produced = (extract_private_icon_png(source, temporary, extraction_target)
                        if source.name.casefold() in _SHELL_PREFERRED_ICON_NAMES else False)
            if not produced:
                produced = extract_embedded_png_icon(source, temporary, extraction_target)
            if not produced:
                produced = extract_private_icon_png(
                    source,
                    temporary,
                    native_extraction_target or extraction_target,
                )
            if not produced:
                produced = extract_shell_item_image_png(
                    source,
                    temporary,
                    native_extraction_target or extraction_target,
                )
            if not produced:
                produced = extract_shell_icon_png(
                    source,
                    temporary,
                    # A large shell icon is safer even for a small destination:
                    # Windows may associate its small slot with a tray/status glyph.
                    small=False,
                )
        if not produced or not temporary.exists():
            return False
        os.replace(temporary, destination)
        return True
    finally:
        with contextlib.suppress(OSError):
            temporary.unlink()


def render_icon_cache_job(
    source: Path,
    raw_path: Path,
    target_size: int,
    *,
    small_shell_icon: bool,
    fit_art_at_scale: float | None,
) -> tuple[bool, bool, str]:
    """Materialize and render one icon entirely inside the renderer process."""

    if not materialize_icon_source_png(
        source,
        raw_path,
        small_shell_icon=small_shell_icon,
        target_size=target_size,
    ):
        return False, False, "no usable icon could be extracted"
    display_path = display_icon_cache_path_for_file(raw_path, target_size)
    raw_header: PngHeader | None = None
    metadata_path = icon_render_metadata_path(display_path)
    if display_path.exists() and metadata_path.exists():
        try:
            cached_metadata = json.loads(metadata_path.read_text(encoding="utf-8"))
        except (OSError, ValueError, TypeError):
            cached_metadata = None
        if icon_render_metadata_is_current(cached_metadata):
            return True, bool(cached_metadata.get("upscaled")), "cached"
    render_metadata: dict[str, Any] = {"_emit_compact": not small_shell_icon}
    rendered = render_icon_png_for_display(
        raw_path,
        display_path,
        target_size,
        fit_art_at_scale=fit_art_at_scale,
        render_metadata=render_metadata,
    )
    normalized_path: Path | None = None
    if not rendered and os.name == "nt":
        normalized_path = display_path.with_name(
            f".{display_path.name}.{os.getpid()}.normalized.png"
        )
        if normalize_image_png_with_gdiplus(raw_path, normalized_path):
            rendered = render_icon_png_for_display(
                normalized_path,
                display_path,
                target_size,
                fit_art_at_scale=fit_art_at_scale,
                render_metadata=render_metadata,
            )
            if rendered:
                render_metadata["normalized_with_gdiplus"] = True
    if normalized_path is not None:
        with contextlib.suppress(OSError):
            normalized_path.unlink()
    if not rendered:
        return False, False, "icon format could not be normalized or rendered"
    render_metadata.setdefault("normalized_with_gdiplus", False)
    extraction_target = max(128, target_size) if small_shell_icon else target_size
    native_ico_size = standalone_ico_native_frame_size(source, extraction_target)
    if raw_header is None:
        raw_header = png_header_fast(raw_path)
    raw_dimensions = raw_header.dimensions if raw_header is not None else None
    render_metadata.update(
        {
            "source_file": str(source),
            "raw_png": str(raw_path),
            "generated_png": str(display_path),
            "target_size": target_size,
            "source_has_explicit_alpha_channel": bool(
                raw_header and raw_header.has_explicit_alpha
            ),
        }
    )
    if native_ico_size is not None:
        render_metadata.update(
            {
                "native_ico_frame_width": native_ico_size[0],
                "native_ico_frame_height": native_ico_size[1],
                "native_ico_frame_preserved": raw_dimensions == native_ico_size,
            }
        )
    write_icon_render_metadata(display_path, render_metadata)
    return True, bool(render_metadata.get("upscaled")), ""


def _icon_worker_com_initialize() -> bool:
    if os.name != "nt":
        return False
    ole32 = ctypes.WinDLL("ole32", use_last_error=True)
    ole32.CoInitializeEx.argtypes = [ctypes.c_void_p, ctypes.c_uint32]
    ole32.CoInitializeEx.restype = ctypes.c_long
    result = int(ole32.CoInitializeEx(None, 0x2))  # COINIT_APARTMENTTHREADED
    return result in {0, 1}  # S_OK or S_FALSE both require CoUninitialize.


def coalesce_icon_gallery_memory_records(
    records: Sequence[tuple[dict[str, Any], bytes]],
) -> list[tuple[dict[str, Any], bytes]]:
    """Collapse visually equivalent in-memory renditions across export sizes."""

    ordered = sorted(
        records,
        key=lambda value: (
            int(value[0]["width"]) * int(value[0]["height"]),
            max(int(value[0]["width"]), int(value[0]["height"])),
        ),
        reverse=True,
    )
    retained: list[tuple[dict[str, Any], bytes, tuple[float, bytes] | None]] = []
    for record, png_data in ordered:
        decoded = read_png_rgba(png_data)
        signature = (
            icon_gallery_visual_signature(decoded[2], decoded[0], decoded[1])
            if decoded is not None
            else None
        )
        match: tuple[dict[str, Any], bytes, tuple[float, bytes] | None] | None = None
        if signature is not None:
            match = next(
                (
                    existing
                    for existing in retained
                    if existing[2] is not None
                    and icon_gallery_signatures_match(signature, existing[2])
                ),
                None,
            )
        if match is None:
            record["represented_sizes"] = [[int(record["width"]), int(record["height"])]]
            retained.append((record, png_data, signature))
            continue
        existing_record = match[0]
        for field in ("sources", "retrievals"):
            for value in record[field]:
                if value not in existing_record[field]:
                    existing_record[field].append(value)
        existing_record["checkerboard"] = bool(existing_record.get("checkerboard")) or bool(
            record.get("checkerboard")
        )
        existing_record["transparent_coverage"] = max(
            float(existing_record.get("transparent_coverage", 0.0)),
            float(record.get("transparent_coverage", 0.0)),
        )
        size = [int(record["width"]), int(record["height"])]
        if size not in existing_record["represented_sizes"]:
            existing_record["represented_sizes"].append(size)
    return [(record, png_data) for record, png_data, _signature in retained]


def append_package_details_rendition(
    records: Sequence[tuple[dict[str, Any], bytes]],
    png_data: bytes,
    source: str,
) -> list[tuple[dict[str, Any], bytes]]:
    """Add the exact processed Details artwork unless identical pixels are present."""

    decoded = read_png_rgba(png_data)
    if decoded is None:
        return list(records)
    width, height, rows = decoded
    retrieval = "WinDevPilot Package Details rendition"
    represented_size = [width, height]
    output = list(records)
    for record, existing_png in output:
        existing = read_png_rgba(existing_png)
        if existing is None or existing[:2] != (width, height) or existing[2] != rows:
            continue
        retrievals = record.setdefault("retrievals", [])
        if retrieval not in retrievals:
            retrievals.append(retrieval)
        if source:
            sources = record.setdefault("sources", [])
            if source not in sources:
                sources.append(source)
        represented_sizes = record.setdefault("represented_sizes", [])
        if represented_size not in represented_sizes:
            represented_sizes.append(represented_size)
        record["package_details_rendition"] = True
        return output

    alpha_values = b"".join(row[3::4] for row in rows)
    transparent_coverage = (
        1.0 - sum(alpha_values) / (255.0 * len(alpha_values))
        if alpha_values
        else 0.0
    )
    output.append(
        (
            {
                "filename": f"WinDevPilot-details-{width}x{height}.png",
                "width": width,
                "height": height,
                "sources": [source] if source else [],
                "retrievals": [retrieval],
                "transparent_coverage": round(transparent_coverage, 5),
                "checkerboard": icon_gallery_needs_checkerboard(rows),
                "represented_sizes": [represented_size],
                "package_details_rendition": True,
            },
            png_data,
        )
    )
    return output


def icon_gallery_worker_main() -> int:
    """Collect Windows icon representations into a bounded in-memory bundle."""

    request = sys.stdin.buffer.read(MAX_ICON_GALLERY_REQUEST_BYTES + 1)
    if len(request) > MAX_ICON_GALLERY_REQUEST_BYTES:
        return 2
    try:
        payload = json.loads(request.decode("utf-8"))
        source_values = payload["sources"]
        if not isinstance(source_values, list) or len(source_values) > 16:
            return 2
        sources = [Path(str(value)) for value in source_values]
        details_value = payload.get("details_rendition")
        details_path: Path | None = None
        details_source = ""
        if isinstance(details_value, dict):
            candidate = Path(str(details_value.get("path", "")))
            if candidate.suffix.casefold() == ".png":
                details_path = candidate
                details_source = str(details_value.get("source", ""))
    except (KeyError, TypeError, UnicodeDecodeError, ValueError):
        return 2
    # WinGet executable links can acquire Shell shortcut overlays. Inspect the
    # real file so an overlay cannot disguise a known placeholder (or duplicate
    # genuine art). This resolves filesystem links, not .lnk shortcut contents.
    resolved_sources: dict[str, Path] = {}
    for source in sources:
        try:
            resolved = source.resolve(strict=True)
            if resolved.is_file():
                resolved_sources.setdefault(os.path.normcase(str(resolved)), resolved)
        except (OSError, RuntimeError):
            continue
    sources = list(resolved_sources.values())
    if details_path is not None and not details_path.is_file():
        details_path = None
    records_by_digest: dict[str, tuple[dict[str, Any], bytes]] = {}
    decoded_by_digest: dict[str, tuple[int, int, list[bytes]]] = {}
    generic_shell_signature: tuple[float, bytes] | None = None
    generic_shell_fallback: tuple[dict[str, Any], bytes] | None = None

    def record_result(
        png_data: bytes,
        filename: str,
        source: Path,
        method: str,
        requested_size: int | None,
    ) -> None:
        nonlocal generic_shell_fallback
        dimensions = png_dimensions_fast(png_data)
        if dimensions is None or dimensions == (1, 1):
            return
        transparent_coverage = 0.0
        uses_transparency = False
        decoded = read_png_rgba(png_data)
        if decoded is not None:
            _decoded_width, _decoded_height, decoded_rows = decoded
            if not any(any(row[3::4]) for row in decoded_rows):
                return
            uses_transparency = icon_gallery_needs_checkerboard(decoded_rows)
            alpha_values = b"".join(row[3::4] for row in decoded_rows)
            if alpha_values:
                transparent_coverage = 1.0 - sum(alpha_values) / (
                    255.0 * len(alpha_values)
                )
        attempt = method + (f" at {requested_size}px" if requested_size else "")
        record = {
            "filename": filename,
            "width": dimensions[0],
            "height": dimensions[1],
            "sources": [str(source)],
            "retrievals": [attempt],
            "transparent_coverage": round(transparent_coverage, 5),
            "checkerboard": uses_transparency,
        }
        if decoded is not None:
            decoded_width, decoded_height, decoded_rows = decoded
            exact_generic = windows_placeholder_pixels(decoded_width, decoded_height, decoded_rows)
            signature = (icon_gallery_visual_signature(decoded_rows, decoded_width, decoded_height)
                         if generic_shell_signature is not None
                         and method in {"IShellItemImageFactory", "SHGetFileInfoW"} else None)
            if exact_generic or (signature is not None and icon_gallery_signatures_match(
                signature, generic_shell_signature
            )):
                record["generic_shell_fallback"] = True
                if generic_shell_fallback is None:
                    generic_shell_fallback = (record, png_data)
                else:
                    previous, previous_png = generic_shell_fallback
                    for field in ("sources", "retrievals"):
                        for value in record[field]:
                            if value not in previous[field]:
                                previous[field].append(value)
                    previous_area = int(previous["width"]) * int(previous["height"])
                    current_area = dimensions[0] * dimensions[1]
                    if current_area > previous_area:
                        record["sources"] = previous["sources"]
                        record["retrievals"] = previous["retrievals"]
                        generic_shell_fallback = (record, png_data)
                    else:
                        generic_shell_fallback = (previous, previous_png)
                return
        if len(records_by_digest) >= MAX_ICON_GALLERY_RESULTS:
            return
        if decoded is not None:
            decoded_width, decoded_height, decoded_rows = decoded
            canonical = hashlib.sha256(struct.pack(">II", decoded_width, decoded_height))
            for row in decoded_rows:
                canonical.update(row)
            digest = canonical.hexdigest()
        else:
            digest = hashlib.sha256(png_data).hexdigest()

        def merge_into(existing: dict[str, Any]) -> None:
            methods = existing["retrievals"]
            if attempt not in methods:
                methods.append(attempt)
            source_names = existing["sources"]
            source_text = str(source)
            if source_text not in source_names:
                source_names.append(source_text)

        existing = records_by_digest.get(digest)
        if existing is not None:
            merge_into(existing[0])
            return
        if decoded is not None:
            decoded_width, decoded_height, decoded_rows = decoded
            for existing_digest, existing_decoded in decoded_by_digest.items():
                existing_width, existing_height, existing_rows = existing_decoded
                if (decoded_width, decoded_height) != (existing_width, existing_height):
                    continue
                if rgba_rows_are_conservative_near_duplicate(
                    decoded_rows,
                    existing_rows,
                    decoded_width,
                    decoded_height,
                ):
                    merge_into(records_by_digest[existing_digest][0])
                    return
        records_by_digest[digest] = (record, png_data)
        if decoded is not None:
            decoded_by_digest[digest] = decoded

    com_initialized = _icon_worker_com_initialize()
    try:
        generic_shell_png = generic_executable_shell_icon_png_bytes()
        if generic_shell_png is not None:
            generic_decoded = read_png_rgba(generic_shell_png)
            if generic_decoded is not None:
                generic_width, generic_height, generic_rows = generic_decoded
                generic_shell_signature = icon_gallery_visual_signature(
                    generic_rows, generic_width, generic_height
                )
        serial = 0
        for source in sources:
            dimensions = png_dimensions_fast(source)
            sizes = {16, 24, 32, 40, 48, 64, 96, 128, 256}
            is_ico = False
            if dimensions is not None:
                sizes.add(max(dimensions))
            with contextlib.suppress(OSError):
                is_ico = source.suffix.casefold() == ".ico"
                if not is_ico:
                    with source.open("rb") as stream:
                        is_ico = stream.read(4) == b"\0\0\1\0"
                if is_ico:
                    sizes.update(
                        max(frame.width, frame.height)
                        for frame in _ico_frames(_read_ico_file_bytes(source))
                    )
            bounded_sizes = sorted(size for size in sizes if 8 <= size <= 256)
            authoritative_ico_found = False

            def filename_for(method_key: str, requested_size: int) -> str:
                nonlocal serial
                serial += 1
                return f"{serial:03d}-{method_key}-{requested_size}.png"

            if source.suffix.casefold() == ".png":
                with contextlib.suppress(OSError):
                    direct = source.read_bytes()
                    record_result(
                        direct,
                        filename_for("direct", max(dimensions or (0, 0))),
                        source,
                        "Direct PNG asset",
                        None,
                    )
                # Shell thumbnail APIs commonly return the generic image-file
                # page rather than the PNG's pixels. The direct asset is both
                # authoritative and higher fidelity, so do not manufacture a
                # lineup of Windows placeholder thumbnails for it.
                continue

            for requested_size in bounded_sizes:
                authoritative_extraction_found = False
                extracted_payload: list[bytes] = []
                if extract_embedded_png_icon(
                    source, None, requested_size, payload_out=extracted_payload
                ):
                    method = (
                        "ICO PNG frame"
                        if source.suffix.casefold() == ".ico"
                        else "Embedded PNG icon resource"
                    )
                    record_result(
                        extracted_payload[-1],
                        filename_for("embedded", requested_size),
                        source,
                        method,
                        requested_size,
                    )
                    authoritative_extraction_found = True
                    if is_ico:
                        authoritative_ico_found = True
                        # The decoded ICO frame is the authoritative source.
                        # Shell APIs only manufacture another scaling of it.
                        continue

                method_out: list[str] = []
                extracted_payload = []
                if extract_private_icon_png(
                    source,
                    None,
                    requested_size,
                    method_out=method_out,
                    payload_out=extracted_payload,
                ):
                    record_result(
                        extracted_payload[-1],
                        filename_for("win32", requested_size),
                        source,
                        method_out[-1] if method_out else "Windows icon extractor",
                        requested_size,
                    )
                    authoritative_extraction_found = True

                if source.suffix.casefold() != ".dll" and not authoritative_extraction_found:
                    extracted_payload = []
                    if extract_shell_item_image_png(
                        source,
                        None,
                        requested_size,
                        payload_out=extracted_payload,
                    ):
                        record_result(
                            extracted_payload[-1],
                            filename_for("shellitem", requested_size),
                            source,
                            "IShellItemImageFactory",
                            requested_size,
                        )

            if source.suffix.casefold() != ".dll" and not authoritative_ico_found:
                extracted_payload = []
                if extract_shell_icon_png(
                    source, None, small=False, payload_out=extracted_payload
                ):
                    record_result(
                        extracted_payload[-1],
                        filename_for("shellfile", 32),
                        source,
                        "SHGetFileInfoW",
                        None,
                    )
    finally:
        if com_initialized:
            with contextlib.suppress(Exception):
                ole32 = ctypes.WinDLL("ole32")
                ole32.CoUninitialize.argtypes = []
                ole32.CoUninitialize.restype = None
                ole32.CoUninitialize()

    gallery_records = list(records_by_digest.values())
    if not gallery_records and generic_shell_fallback is not None:
        gallery_records.append(generic_shell_fallback)
    coalesced = coalesce_icon_gallery_memory_records(gallery_records)
    if details_path is not None:
        with contextlib.suppress(OSError):
            if details_path.stat().st_size <= 8 * 1024 * 1024:
                coalesced = append_package_details_rendition(
                    coalesced,
                    details_path.read_bytes(),
                    details_source,
                )
    items = sorted(
        coalesced,
        key=lambda value: (
            max(int(value[0]["width"]), int(value[0]["height"])),
            int(value[0]["width"]) * int(value[0]["height"]),
            str(value[0]["filename"]),
        ),
    )
    bundle = pack_icon_gallery_memory_items(items)
    sys.stdout.buffer.write(serialize_icon_gallery_bundle(bundle))
    return 0


def icon_showcase_contrast_backdrop(image: Any, backdrop: str) -> str:
    """Bounded native pixel sampling; transparent pixels never count as artwork."""
    if backdrop == "checkerboard":
        return backdrop
    width, height = image.width(), image.height()
    nx, ny = min(16, width), min(16, height)
    background = 0 if backdrop == "black" else 255
    visible = False
    for sy in range(ny):
        y = min(height - 1, (2 * sy + 1) * height // (2 * ny))
        for sx in range(nx):
            x = min(width - 1, (2 * sx + 1) * width // (2 * nx))
            if image.transparency_get(x, y):
                continue
            visible = True
            if max(abs(int(channel) - background) for channel in image.get(x, y)) > 40:
                return backdrop  # Ordinary colored art usually needs just one sample.
    # Sparse artwork may fall between samples. A checkerboard is safe when the
    # bounded probe finds no visible pixels; never infer that the image is blank.
    return "gray" if visible else "checkerboard"


def icon_showcase_background(modifier_state: int) -> str:
    """Choose the inspection backdrop; Ctrl takes precedence over Shift."""

    if modifier_state & 0x0004:
        return "checkerboard"
    return "black" if modifier_state & 0x0001 else "white"


def _scale_rgba_nearest(
    rows: Sequence[bytes], width: int, height: int, target_width: int, target_height: int,
) -> list[bytes]:
    """Copy nearest pixel centers verbatim, including their original alpha."""

    if min(width, height, target_width, target_height) <= 0:
        return []
    if len(rows) != height or any(len(row) != width * 4 for row in rows):
        return []
    offsets = [min(width - 1, (2 * x + 1) * width // (2 * target_width)) * 4
               for x in range(target_width)]
    scaled: list[bytes] = []
    previous_y = -1
    for y in range(target_height):
        source_y = min(height - 1, (2 * y + 1) * height // (2 * target_height))
        if source_y != previous_y:
            row = rows[source_y]
            scaled_row = b"".join(row[offset:offset + 4] for offset in offsets)
            previous_y = source_y
        scaled.append(scaled_row)
    return scaled


def _showcase_finish_rows(
    rows: Sequence[bytes], width: int, height: int, backdrop: str,
) -> tuple[list[bytes], bool]:
    """Reserve an exterior margin; outline only mostly white art on white."""

    outline_needed = backdrop == "white" and _dominant_artwork_outline_tone(rows, width) == "dark"
    padded_width, padded_height, padded = _pad_rgba(rows, width, height, 4)
    if not outline_needed:
        return padded, False
    applied: list[str] = []
    outlined = add_adaptive_outline_to_rgba(
        padded, padded_width, padded_height, forced_tone="dark", outline_result=applied,
    )
    return outlined, bool(applied)


def icon_showcase_worker_main() -> int:
    """Prepare one 3x lineup preview through memory-only binary pipes."""

    request = sys.stdin.buffer.read(MAX_ICON_SHOWCASE_WIRE_BYTES + 1)
    if len(request) > MAX_ICON_SHOWCASE_WIRE_BYTES or len(request) < 5:
        return 2
    try:
        metadata_size = struct.unpack("<I", request[:4])[0]
        metadata_end = 4 + metadata_size
        if not 4 < metadata_end < len(request):
            return 2
        payload = json.loads(request[4:metadata_end].decode("utf-8"))
        art_target_width = int(payload["artwork_width"])
        art_target_height = int(payload["artwork_height"])
        target_width, target_height = art_target_width + 8, art_target_height + 8
        backdrop = payload.get("backdrop", "white")
        if backdrop not in ("white", "black", "checkerboard"):
            return 2
    except (KeyError, TypeError, UnicodeDecodeError, ValueError):
        return 2
    if (
        not 1 <= art_target_width <= MAX_ICON_SHOWCASE_SIZE
        or not 1 <= art_target_height <= MAX_ICON_SHOWCASE_SIZE
        or not 1 <= target_width <= MAX_ICON_SHOWCASE_SIZE
        or not 1 <= target_height <= MAX_ICON_SHOWCASE_SIZE
    ):
        return 2
    decoded = read_png_rgba(request[metadata_end:])
    if decoded is None:
        return 3
    source_width, source_height, rows = decoded
    if "integer_subsample" in payload or "integer_zoom" in payload:
        subsample = payload.get("integer_subsample")
        zoom = payload.get("integer_zoom")
        if (type(subsample) is not int or type(zoom) is not int
                or not 1 <= subsample <= max(source_width, source_height)
                or not 1 <= zoom <= 3
                or math.ceil(source_width / subsample) * zoom != art_target_width
                or math.ceil(source_height / subsample) * zoom != art_target_height):
            return 2
        rows = [b"".join(row[x:x + 4] for x in range(0, source_width * 4, subsample * 4))
                for row in rows[::subsample]]
        source_width = math.ceil(source_width / subsample)
        source_height = math.ceil(source_height / subsample)
    # Nearest-neighbor sampling preserves source colors and alpha without smoothing.
    scaled = _scale_rgba_nearest(
        rows,
        source_width,
        source_height,
        art_target_width,
        art_target_height,
    )
    mode = "nearest-neighbor-upscale" if (
        art_target_width > source_width or art_target_height > source_height
    ) else "nearest-neighbor-fit"
    if len(scaled) != art_target_height:
        return 4
    scaled, outlined = _showcase_finish_rows(scaled, art_target_width, art_target_height, backdrop)
    if outlined:
        mode += "+outline-dark"
    # Showcase PNGs are transient pipe payloads. Level 1 materially reduces
    # latency for very large previews; durable icon-cache PNGs retain level 6.
    rendered = rgba_png_bytes(
        target_width,
        target_height,
        scaled,
        compression_level=1,
    )
    response_metadata = json.dumps(
        {
            "width": target_width,
            "height": target_height,
            "artwork_width": art_target_width,
            "artwork_height": art_target_height,
            "mode": mode,
            "analysis": {"white_on_white_outline": outlined},
        },
        separators=(",", ":"),
    ).encode("utf-8")
    sys.stdout.buffer.write(struct.pack("<I", len(response_metadata)))
    sys.stdout.buffer.write(response_metadata)
    sys.stdout.buffer.write(rendered)
    return 0


def icon_render_worker_main() -> int:
    """Serve sequential icon jobs over JSONL until stdin closes."""

    input_stream = getattr(sys.stdin, "buffer", None)
    output_stream = getattr(sys.stdout, "buffer", None)
    if input_stream is None or output_stream is None:
        return 2
    com_initialized = _icon_worker_com_initialize()
    try:
        for raw_line in input_stream:
            if len(raw_line) > MAX_ICON_RENDER_MESSAGE_BYTES:
                return 2
            job: Any = {}
            try:
                job = json.loads(raw_line.decode("utf-8"))
                job_id = int(job["id"])
                target_size = int(job["size"])
                source = Path(str(job["source"]))
                raw_path = Path(str(job["raw_path"]))
                small_shell_icon = bool(job["small_shell_icon"])
                fit_value = job.get("fit_art_at_scale")
                fit_art_at_scale = float(fit_value) if fit_value is not None else None
                if not 8 <= target_size <= 1024:
                    raise ValueError("target size is outside the supported range")
                ok, upscaled, reason = render_icon_cache_job(
                    source,
                    raw_path,
                    target_size,
                    small_shell_icon=small_shell_icon,
                    fit_art_at_scale=fit_art_at_scale,
                )
            except Exception as exc:
                job_id = int(job.get("id", -1)) if isinstance(job, dict) else -1
                ok = False
                upscaled = False
                reason = f"{type(exc).__name__}: {exc}"[:1000]
            response = json.dumps(
                {
                    "id": job_id,
                    "ok": ok,
                    "upscaled": upscaled,
                    "reason": reason,
                },
                ensure_ascii=False,
                separators=(",", ":"),
            ).encode("utf-8")
            output_stream.write(response + b"\n")
            output_stream.flush()
    finally:
        if com_initialized:
            with contextlib.suppress(Exception):
                ole32 = ctypes.WinDLL("ole32")
                ole32.CoUninitialize.argtypes = []
                ole32.CoUninitialize.restype = None
                ole32.CoUninitialize()
    return 0


# ==================== Background icon rendering ====================

@dataclasses.dataclass(slots=True)
class IconRenderRequest:
    generation: int
    source: Path
    raw_path: Path
    target_size: int
    small_shell_icon: bool
    fit_art_at_scale: float | None
    coalesce_key: str = ""
    completion: threading.Event = dataclasses.field(default_factory=threading.Event)
    result: tuple[bool, bool, str] = (False, False, "renderer did not complete")


class IconRenderCoordinator:
    """Own one hidden renderer child and serialize prioritized icon requests."""

    def __init__(self) -> None:
        self._requests: queue.PriorityQueue[tuple[int, int, IconRenderRequest | None]] = (
            queue.PriorityQueue()
        )
        self._state_lock = threading.Lock()
        self._idle_condition = threading.Condition(self._state_lock)
        self._generation = 0
        self._sequence = 0
        self._job_id = 0
        self._inflight = 0
        self._active = False
        self._active_request: IconRenderRequest | None = None
        self._latest_coalesced: dict[str, IconRenderRequest] = {}
        self._shutdown = False
        self._child: subprocess.Popen[bytes] | None = None
        self._responses: queue.Queue[bytes | None] | None = None
        self._thread = threading.Thread(
            target=self._run,
            name="wdp-icon-render-coordinator",
            daemon=True,
        )
        self._thread.start()

    def prepare(
        self,
        source: Path,
        raw_path: Path,
        target_size: int,
        *,
        small_shell_icon: bool,
        fit_art_at_scale: float | None,
        generation: int,
        priority: int,
        coalesce_key: str = "",
    ) -> tuple[bool, bool, str]:
        if threading.current_thread() is threading.main_thread():
            raise RuntimeError("icon rendering must never wait on Tk's main thread")
        request = IconRenderRequest(
            generation=generation,
            source=source,
            raw_path=raw_path,
            target_size=target_size,
            small_shell_icon=small_shell_icon,
            fit_art_at_scale=fit_art_at_scale,
            coalesce_key=coalesce_key,
        )
        superseded_child: subprocess.Popen[bytes] | None = None
        with self._state_lock:
            if self._shutdown or generation != self._generation:
                return False, False, "render request was superseded"
            self._sequence += 1
            sequence = self._sequence
            if coalesce_key:
                previous = self._latest_coalesced.get(coalesce_key)
                self._latest_coalesced[coalesce_key] = request
                if previous is self._active_request:
                    superseded_child = self._child
                    self._child = None
                    self._responses = None
            # Queue publication is part of the state transition. Otherwise a
            # concurrent shutdown could enqueue its sentinel first and strand
            # this caller after the coordinator thread exits.
            # The newest request in a coalesced stream sorts first; obsolete
            # requests are rejected by _request_is_current without rendering.
            queue_order = -sequence if coalesce_key else sequence
            self._inflight += 1
            self._requests.put((priority, queue_order, request))
        if superseded_child is not None:
            self._terminate_child(superseded_child)
        if not request.completion.wait(ICON_RENDER_JOB_TIMEOUT_SECONDS + 5.0):
            return False, False, "renderer coordinator timed out"
        return request.result

    def set_generation(self, generation: int, *, terminate: bool = True) -> None:
        with self._state_lock:
            if self._shutdown:
                return
            self._generation = generation
            self._latest_coalesced.clear()
            child = self._child if terminate else None
            if terminate:
                self._child = None
                self._responses = None
        if child is not None:
            self._terminate_child(child)

    def warm(self, generation: int) -> bool:
        """Start the hidden renderer ahead of its first job on a worker thread."""

        if threading.current_thread() is threading.main_thread():
            raise RuntimeError("icon renderer warm-up must not run on Tk's main thread")
        return self._ensure_child(generation) is not None

    def wait_idle(self, timeout: float) -> bool:
        deadline = time.monotonic() + max(0.0, timeout)
        with self._idle_condition:
            while self._active or self._inflight or not self._requests.empty():
                remaining = deadline - time.monotonic()
                if remaining <= 0:
                    return False
                self._idle_condition.wait(remaining)
            return True

    def shutdown(self, timeout: float = 0.5) -> None:
        with self._state_lock:
            if self._shutdown:
                return
            self._shutdown = True
            self._generation += 1
            self._latest_coalesced.clear()
            child = self._child
            self._child = None
            self._responses = None
            while True:
                try:
                    _priority, _sequence, request = self._requests.get_nowait()
                except queue.Empty:
                    break
                if request is not None:
                    request.result = (False, False, "renderer is shutting down")
                    request.completion.set()
                    self._inflight -= 1
                self._requests.task_done()
            self._sequence += 1
            self._requests.put((-100, self._sequence, None))
            self._idle_condition.notify_all()
        if child is not None:
            self._terminate_child(child)
        self._thread.join(timeout=max(0.0, timeout))

    def _request_is_current(self, request: IconRenderRequest) -> bool:
        with self._state_lock:
            return (
                not self._shutdown
                and request.generation == self._generation
                and (
                    not request.coalesce_key
                    or self._latest_coalesced.get(request.coalesce_key) is request
                )
            )

    def _run(self) -> None:
        while True:
            _priority, _sequence, request = self._requests.get()
            if request is None:
                self._requests.task_done()
                return
            with self._idle_condition:
                self._active = True
                self._active_request = request
            try:
                if not self._request_is_current(request):
                    request.result = (False, False, "render request was superseded")
                else:
                    request.result = self._execute_with_recovery(request)
                    if not self._request_is_current(request):
                        request.result = (False, False, "render request was superseded")
            finally:
                request.completion.set()
                self._requests.task_done()
                with self._idle_condition:
                    self._inflight -= 1
                    self._active = False
                    if self._active_request is request:
                        self._active_request = None
                    if (
                        request.coalesce_key
                        and self._latest_coalesced.get(request.coalesce_key) is request
                    ):
                        self._latest_coalesced.pop(request.coalesce_key, None)
                    self._idle_condition.notify_all()

    def _execute_with_recovery(self, request: IconRenderRequest) -> tuple[bool, bool, str]:
        last_reason = "renderer did not respond"
        for _attempt in range(2):
            if not self._request_is_current(request):
                return False, False, "render request was superseded"
            child_state = self._ensure_child(request.generation)
            if child_state is None:
                if self._request_is_current(request):
                    return False, False, "renderer child could not be started"
                return False, False, "render request was superseded"
            child, responses = child_state
            if not self._request_is_current(request):
                return False, False, "render request was superseded"
            with self._state_lock:
                self._job_id += 1
                job_id = self._job_id
            job = {
                "id": job_id,
                "source": str(request.source),
                "raw_path": str(request.raw_path),
                "size": request.target_size,
                "small_shell_icon": request.small_shell_icon,
                "fit_art_at_scale": request.fit_art_at_scale,
            }
            try:
                assert child.stdin is not None
                child.stdin.write(
                    json.dumps(job, ensure_ascii=False, separators=(",", ":")).encode("utf-8")
                    + b"\n"
                )
                child.stdin.flush()
                response_line = responses.get(timeout=ICON_RENDER_JOB_TIMEOUT_SECONDS)
                if response_line is None:
                    raise EOFError("renderer child exited")
                if len(response_line) > MAX_ICON_RENDER_MESSAGE_BYTES:
                    raise ValueError("renderer response exceeded its size limit")
                response = json.loads(response_line.decode("utf-8"))
                if int(response.get("id", -1)) != job_id:
                    raise ValueError("renderer response did not match its request")
                return (
                    bool(response.get("ok")),
                    bool(response.get("upscaled")),
                    str(response.get("reason", "")),
                )
            except queue.Empty as exc:
                last_reason = f"{type(exc).__name__}: renderer job timed out"
                self._discard_child(child)
                # A hung source is deterministic often enough that immediately
                # repeating its full timeout is harmful. Crash/protocol errors
                # still get one clean-child retry below.
                return False, False, last_reason
            except (OSError, EOFError, ValueError, json.JSONDecodeError) as exc:
                last_reason = f"{type(exc).__name__}: {exc}"
                self._discard_child(child)
        return False, False, last_reason

    def _ensure_child(
        self, generation: int
    ) -> tuple[subprocess.Popen[bytes], queue.Queue[bytes | None]] | None:
        with self._state_lock:
            child = self._child
            responses = self._responses
            if (
                not self._shutdown
                and generation == self._generation
                and child is not None
                and responses is not None
                and child.poll() is None
            ):
                return child, responses
            if self._shutdown or generation != self._generation:
                return None
        try:
            new_child = subprocess.Popen(
                cached_self_command("--render-worker"),
                stdin=subprocess.PIPE,
                stdout=subprocess.PIPE,
                stderr=subprocess.DEVNULL,
                cwd=str(SCRIPT_PATH.parent),
                creationflags=CREATE_NO_WINDOW | BELOW_NORMAL_PRIORITY_CLASS,
            )
        except OSError:
            return None
        new_responses: queue.Queue[bytes | None] = queue.Queue()

        def read_responses() -> None:
            assert new_child.stdout is not None
            try:
                for line in new_child.stdout:
                    new_responses.put(line.rstrip(b"\r\n"))
            except (OSError, ValueError):
                # An abandoned child closes its pipe after termination. The
                # reader is disposable; its queue sentinel is the only state
                # transition the coordinator needs.
                pass
            finally:
                new_responses.put(None)

        threading.Thread(
            target=read_responses,
            name="wdp-icon-render-reader",
            daemon=True,
        ).start()
        with self._state_lock:
            if self._shutdown or generation != self._generation:
                install_child = False
            else:
                self._child = new_child
                self._responses = new_responses
                install_child = True
        if not install_child:
            self._terminate_child(new_child)
            return None
        return new_child, new_responses

    @staticmethod
    def _terminate_child(child: subprocess.Popen[bytes], timeout: float = 0.25) -> None:
        """Bound child exit, then release every parent-side pipe handle.

        Terminating before closing stdout lets the blocking reader observe EOF
        naturally on Windows. Closing a buffered stream while another thread
        owns its read lock can otherwise turn cleanup itself into a hang.
        """

        if child.poll() is None:
            with contextlib.suppress(OSError):
                child.terminate()
            try:
                child.wait(timeout=max(0.0, timeout))
            except subprocess.TimeoutExpired:
                with contextlib.suppress(OSError):
                    child.kill()
                with contextlib.suppress(OSError, subprocess.TimeoutExpired):
                    child.wait(timeout=max(0.0, timeout))
        for stream in (child.stdin, child.stdout):
            if stream is not None:
                with contextlib.suppress(OSError, ValueError):
                    stream.close()

    def _discard_child(self, child: subprocess.Popen[bytes]) -> None:
        with self._state_lock:
            if self._child is child:
                self._child = None
                self._responses = None
        self._terminate_child(child)


def warm_icon_cache_index_isolated(
    items: Sequence[UpdateItem],
    icon_size: int,
    palette_mode: str,
    source_target_size: int,
) -> tuple[dict[str, Path | None], list[str], list[str], str]:
    """Match packages to warm icon files outside Tk's interpreter process."""
    records = [
        {
            "key": item.key,
            "provider": item.provider,
            "package_id": item.package_id,
            "name": item.name,
            "icon_source": item.icon_source,
            "installed_location": item.installed_location,
        }
        for item in items
    ]
    request = json.dumps(records, ensure_ascii=False).encode("utf-8")
    if len(request) > MAX_ICON_INDEX_BYTES:
        return {}, [], [], "icon index request exceeded its size limit"
    try:
        completed = subprocess.run(
            [
                *cached_self_command(),
                "--index-icon-cache",
                str(icon_size),
                palette_mode,
                str(source_target_size),
            ],
            input=request,
            stdout=subprocess.PIPE,
            stderr=subprocess.DEVNULL,
            timeout=90,
            check=False,
            cwd=str(SCRIPT_PATH.parent),
            creationflags=CREATE_NO_WINDOW | BELOW_NORMAL_PRIORITY_CLASS,
        )
    except (OSError, subprocess.SubprocessError) as exc:
        return {}, [], [], f"{type(exc).__name__}: {exc}"
    if completed.returncode != 0:
        return {}, [], [], f"icon index helper exited with code {completed.returncode}"
    try:
        payload = json.loads(completed.stdout.decode("utf-8"))
        sources = {
            str(key): Path(value) if value else None
            for key, value in dict(payload.get("sources", {})).items()
        }
        ready_keys = [str(value) for value in payload.get("ready_keys", [])]
        unavailable_keys = [str(value) for value in payload.get("unavailable_keys", [])]
    except (UnicodeDecodeError, TypeError, ValueError) as exc:
        return {}, [], [], f"invalid icon index response: {type(exc).__name__}: {exc}"
    return sources, ready_keys, unavailable_keys, ""


def icon_cache_index_helper(icon_size: int, palette_mode: str, source_target_size: int) -> int:
    """Internal subprocess entry point for CPU-heavy warm-cache matching."""
    request = sys.stdin.buffer.read(MAX_ICON_INDEX_BYTES + 1)
    if len(request) > MAX_ICON_INDEX_BYTES:
        return 2
    try:
        records = json.loads(request.decode("utf-8"))
    except (UnicodeDecodeError, json.JSONDecodeError):
        return 2
    if not isinstance(records, list):
        return 2
    sources: dict[str, str] = {}
    ready_keys: list[str] = []
    unavailable_keys: list[str] = []
    render_states: dict[tuple[Path, int], str] = {}
    for record in records:
        if not isinstance(record, dict):
            return 2
        try:
            item_key = str(record["key"])
            provider = str(record["provider"])
            package_id = str(record["package_id"])
            name = str(record["name"])
            icon_source = str(record.get("icon_source", ""))
            installed_location = str(record.get("installed_location", ""))
        except KeyError:
            return 2
        source = resolve_icon_source_fields(
            provider,
            icon_source,
            package_id,
            installed_location,
            name,
            source_target_size,
        )
        sources[item_key] = str(source) if source is not None else ""
        if source is None:
            continue
        raw_path = package_icon_cache_path_for_fields(
            provider,
            package_id,
            name,
            source,
            icon_size,
            palette_mode,
        )
        # Presence alone is insufficient: renderer/extraction revisions use
        # the sidecar metadata to retire stale artwork without deleting the
        # whole cache. Warm-start indexing must honor the same contract as the
        # foreground/detail paths or it can briefly resurrect an old icon.
        render_key = (raw_path, icon_size)
        state = render_states.get(render_key)
        if state is None:
            if rendered_icon_cache_is_current(raw_path, icon_size):
                state = "ready"
            elif icon_render_miss_is_current(raw_path, icon_size):
                state = "unavailable"
            else:
                state = "missing"
            render_states[render_key] = state
        if state == "ready":
            ready_keys.append(item_key)
        elif state == "unavailable":
            unavailable_keys.append(item_key)
    sys.stdout.write(
        json.dumps(
            {
                "sources": sources,
                "ready_keys": ready_keys,
                "unavailable_keys": unavailable_keys,
            }
        )
    )
    return 0


def rgba_rows_have_visual_detail(rows: Sequence[bytes], width: int, height: int) -> bool:
    """Tcl-free visual-detail check with alpha-aware silhouette handling.

    Runs without any Tcl round-trips, which keeps icon memory loads inside
    their UI time budget. Its transparent-pixel rules intentionally differ
    from the Tk image fallback, whose pixel API does not expose alpha reliably.
    """

    if width <= 0 or height <= 0:
        return False
    colors: set[tuple[int, int, int]] = set()
    luminance_values: set[int] = set()
    opaque_samples = 0
    transparent_samples = 0
    step_x = max(1, width // 12)
    step_y = max(1, height // 12)
    for y in range(0, height, step_y):
        row = rows[y]
        for x in range(0, width, step_x):
            index = x * 4
            # Hidden RGB in fully transparent PNG pixels is not artwork. Some
            # Store assets retain arbitrary color there; counting it could
            # promote a visually blank tile over the recognizable logo.
            if row[index + 3] <= 24:
                transparent_samples += 1
                continue
            red, green, blue = row[index], row[index + 1], row[index + 2]
            opaque_samples += 1
            colors.add((red // 32, green // 32, blue // 32))
            luminance_values.add((red * 299 + green * 587 + blue * 114) // 1000 // 24)
            if len(colors) >= 2 and len(luminance_values) >= 2:
                return True
    if opaque_samples < 6:
        return False
    # A substantial alpha-defined silhouette is real icon geometry even when
    # every visible pixel is the same white, black, or gray. Rejecting such
    # marks caused excellent unplated AppX artwork (including OpenAI's knot) to
    # lose to an opaque Store tile. Tiny specks still fail the sample minimum.
    if transparent_samples >= 6:
        return True
    if len(colors) == 1:
        quantized = next(iter(colors))
        red, green, blue = (component * 32 + 16 for component in quantized)
        saturation = max(red, green, blue) - min(red, green, blue)
        luminance = (red * 299 + green * 587 + blue * 114) // 1000
        return saturation >= 80 and 40 <= luminance <= 215
    return len(colors) >= 2 and len(luminance_values) >= 2


def icon_png_has_visual_detail(path: Path) -> bool | None:
    """Detail-check a cached PNG without Tcl; None when undecodable here."""

    decoded = read_png_rgba(path)
    if decoded is None:
        return None
    width, height, rows = decoded
    return rgba_rows_have_visual_detail(rows, width, height)


def tk_image_has_visual_detail(image: Any) -> bool:
    """Reject blank or near-monochrome icons that look like missing artwork."""

    try:
        width = int(image.width())
        height = int(image.height())
    except Exception:
        return True
    if width <= 0 or height <= 0:
        return False
    colors: set[tuple[int, int, int]] = set()
    luminance_values: set[int] = set()
    opaque_samples = 0
    step_x = max(1, width // 12)
    step_y = max(1, height // 12)
    for y in range(0, height, step_y):
        for x in range(0, width, step_x):
            try:
                sample = image.get(x, y)
            except Exception:
                continue
            if isinstance(sample, str):
                if sample in {"", "{}"}:
                    continue
                if sample.startswith("#") and len(sample) >= 7:
                    red = int(sample[1:3], 16)
                    green = int(sample[3:5], 16)
                    blue = int(sample[5:7], 16)
                else:
                    continue
            else:
                if len(sample) < 3:
                    continue
                red, green, blue = int(sample[0]), int(sample[1]), int(sample[2])
            opaque_samples += 1
            quantized = (red // 32, green // 32, blue // 32)
            colors.add(quantized)
            luminance_values.add((red * 299 + green * 587 + blue * 114) // 1000 // 24)
            if len(colors) >= 2 and len(luminance_values) >= 2:
                return True
    if opaque_samples < 6:
        return False
    if len(colors) == 1:
        quantized = next(iter(colors))
        red, green, blue = (component * 32 + 16 for component in quantized)
        saturation = max(red, green, blue) - min(red, green, blue)
        luminance = (red * 299 + green * 587 + blue * 114) // 1000
        return saturation >= 80 and 40 <= luminance <= 215
    return len(colors) >= 2 and len(luminance_values) >= 2


def pip_show_version(output: str) -> str:
    for line in output.splitlines():
        if line.casefold().startswith("version:"):
            return line.split(":", 1)[1].strip()
    return ""


def pip_list_json_version(output: str, package_id: str) -> str:
    start = output.find("[")
    if start < 0:
        return ""
    try:
        data, _end = json.JSONDecoder().raw_decode(output[start:])
    except json.JSONDecodeError:
        return ""
    if not isinstance(data, list):
        return ""
    folded_id = package_id.casefold()
    for entry in data:
        if not isinstance(entry, dict):
            continue
        if str(entry.get("name", "")).casefold() == folded_id:
            return str(entry.get("version", ""))
    return ""


def normalized_package_name(value: str) -> str:
    return re.sub(r"[^a-z0-9]+", "", value.casefold())


def registry_install_technology(
    _key_name: str, windows_installer: Any, uninstall_string: str
) -> str:
    # A GUID-shaped uninstall key is not proof of MSI ownership; many vendor
    # bootstrapper EXEs use product-code-looking keys. Trust only explicit
    # WindowsInstaller metadata or an msiexec command before using MSI APIs.
    if str(windows_installer).strip() == "1":
        return "msi"
    folded_uninstall = str(uninstall_string).casefold()
    if "msiexec" in folded_uninstall:
        return "msi"
    if uninstall_string:
        return "exe"
    return "unknown"


def local_executable_from_command(command: str) -> str:
    """Extract an existing absolute executable from a registry command line."""

    value = os.path.expandvars(str(command).strip())
    if not value:
        return ""
    if value.startswith('"'):
        end = value.find('"', 1)
        candidate = value[1:end] if end > 1 else ""
    else:
        match = re.match(r"(?i)^(.+?\.exe)(?:\s|$)", value)
        candidate = match.group(1).strip() if match else ""
    path = Path(candidate)
    with contextlib.suppress(OSError):
        if path.is_absolute() and path.is_file() and path.suffix.casefold() == ".exe":
            return str(path)
    return ""


def msi_product_info(product_code: str, property_name: str) -> str:
    """Read an authoritative Windows Installer property without elevation."""

    if os.name != "nt" or not MSI_PRODUCT_CODE_RE.fullmatch(product_code):
        return ""
    try:
        msi = ctypes.WinDLL("msi", use_last_error=True)
        get_product_info = msi.MsiGetProductInfoW
        get_product_info.argtypes = [
            ctypes.c_wchar_p,
            ctypes.c_wchar_p,
            ctypes.c_wchar_p,
            ctypes.POINTER(ctypes.c_uint32),
        ]
        get_product_info.restype = ctypes.c_uint32
        length = ctypes.c_uint32(0)
        result = int(get_product_info(product_code, property_name, None, ctypes.byref(length)))
        if result not in {0, 234} or length.value > 32_767:
            return ""
        buffer = ctypes.create_unicode_buffer(length.value + 1)
        capacity = ctypes.c_uint32(len(buffer))
        if (
            get_product_info(
                product_code,
                property_name,
                buffer,
                ctypes.byref(capacity),
            )
            != 0
        ):
            return ""
        return os.path.expandvars(buffer.value.strip().strip('"'))
    except (AttributeError, OSError):
        return ""


# Optional date metadata must not prevent an otherwise valid package from being
# enumerated. Reset per record so a missing date never inherits its predecessor's.
WINDOWS_PACKAGE_DATE_SCRIPT = (
    "$date='';$installedDate=$_.InstalledDate;"
    "if($null -ne $installedDate){"
    "$date=$installedDate.ToUniversalTime().ToString("
    "'yyyy-MM-ddTHH:mm:ss.ffffffZ',[Globalization.CultureInfo]::InvariantCulture);};"
)


def windows_app_package_installed_dates() -> tuple[dict[str, tuple[str, str]], str]:
    """Read current-user Package.InstalledDate through the official WinRT API."""

    if os.name != "nt" or shutil.which("powershell.exe") is None:
        return {}, "Windows PowerShell is unavailable"
    script = (
        "$ErrorActionPreference='Stop';"
        "$null=[Windows.Management.Deployment.PackageManager,Windows.Management.Deployment,"
        "ContentType=WindowsRuntime];"
        "$pm=[Windows.Management.Deployment.PackageManager]::new();"
        "$sid=[Security.Principal.WindowsIdentity]::GetCurrent().User.Value;"
        "$rows=@($pm.FindPackagesForUser($sid)|ForEach-Object{if($_ -and $_.Id){"
        + WINDOWS_PACKAGE_DATE_SCRIPT +
        "[pscustomobject]@{full_name=$_.Id.FullName;installed_timestamp=$date}}});"
        "[Console]::Out.Write(($rows|ConvertTo-Json -Compress -Depth 3))"
    )
    result = run_capture(
        (
            "powershell.exe",
            "-NoLogo",
            "-NoProfile",
            "-NonInteractive",
            "-Command",
            script,
        ),
        timeout=30,
    )
    if result.returncode != 0 or result.exception:
        detail = result.exception or clean_output(result.output).strip() or "no output"
        return {}, detail[-500:]
    try:
        payload = json.loads(clean_output(result.output) or "[]")
    except (TypeError, ValueError) as exc:
        return {}, f"invalid PackageManager JSON: {exc}"
    records = [payload] if isinstance(payload, dict) else payload
    if not isinstance(records, list):
        return {}, "PackageManager returned an unexpected JSON root"
    installed_dates: dict[str, tuple[str, str]] = {}
    for record in records:
        if not isinstance(record, Mapping):
            continue
        full_name = str(record.get("full_name", "")).strip()
        installed_timestamp, precision = normalize_wall_clock_timestamp(
            record.get("installed_timestamp", "")
        )
        if full_name and len(full_name) <= 512 and installed_timestamp:
            installed_dates[full_name.casefold()] = (installed_timestamp, precision)
    return installed_dates, ""


def microsoft_store_package_inventory() -> tuple[list[dict[str, Any]], str]:
    """Enumerate Store-signed packages for the launching Windows account.

    PackageManager is the supported per-user inventory API.  Keeping this
    query in the non-elevated account is important: another administrator
    identity has a different Store library and package registration set.
    """

    if os.name != "nt" or shutil.which("powershell.exe") is None:
        return [], "Windows PowerShell is unavailable"
    script = (
        "$ErrorActionPreference='Stop';"
        "$null=[Windows.Management.Deployment.PackageManager,Windows.Management.Deployment,"
        "ContentType=WindowsRuntime];"
        "$pm=[Windows.Management.Deployment.PackageManager]::new();"
        "$sid=[Security.Principal.WindowsIdentity]::GetCurrent().User.Value;"
        "$rows=@($pm.FindPackagesForUser($sid)|ForEach-Object{"
        "if($_ -and $_.Id){"
        + WINDOWS_PACKAGE_DATE_SCRIPT +
        "if($_.IsFramework -or $_.IsResourcePackage -or "
        "[string]$_.SignatureKind -ne 'Store'){"
        "[pscustomobject]@{date_only=$true;full_name=$_.Id.FullName;"
        "installed_timestamp=$date}}else{"
        "$location=if($_.InstalledLocation){$_.InstalledLocation.Path}else{''};"
        "$launchable=$false;$launchIds=@();"
        "if($location){$manifest=Join-Path $location 'AppxManifest.xml';"
        "if(Test-Path -LiteralPath $manifest){try{$xml=[xml](Get-Content -LiteralPath "
        "$manifest -Raw -ErrorAction Stop);$apps=@($xml.SelectNodes("
        "\"/*[local-name()='Package']/*[local-name()='Applications']/*[local-name()='Application']\"));"
        "$visibleApps=@($apps|Where-Object{$visual=$_.SelectSingleNode("
        "\"./*[local-name()='VisualElements']\");$entry=@($visual.Attributes|Where-Object{"
        "$_.LocalName -eq 'AppListEntry'}|Select-Object -First 1);"
        "$visual -and (-not $entry -or $entry.Value -ne 'none')});$launchable=$visibleApps.Count -gt 0;"
        "$launchIds=@($visibleApps|ForEach-Object{$_.GetAttribute('Id')})}catch{}}};"
        "[pscustomobject]@{name=$_.Id.Name;full_name=$_.Id.FullName;family=$_.Id.FamilyName;"
        "display_name=$_.DisplayName;publisher=$_.PublisherDisplayName;description=$_.Description;"
        "version=('{0}.{1}.{2}.{3}' -f $_.Id.Version.Major,$_.Id.Version.Minor,"
        "$_.Id.Version.Build,$_.Id.Version.Revision);architecture=$_.Id.Architecture.ToString();"
        "installed_location=$location;installed_timestamp=$date;"
        "logo=if($_.Logo){$_.Logo.OriginalString}else{''};launchable=$launchable;"
        "launch_ids=@($launchIds)}}}});"
        "[Console]::Out.Write(($rows|ConvertTo-Json -Compress -Depth 4))"
    )
    result = run_capture(
        (
            "powershell.exe",
            "-NoLogo",
            "-NoProfile",
            "-NonInteractive",
            "-Command",
            script,
        ),
        timeout=60,
    )
    if result.returncode != 0 or result.exception:
        detail = result.exception or clean_output(result.output).strip() or "no output"
        return [], detail[-500:]
    try:
        payload = json.loads(clean_output(result.output) or "[]")
    except (TypeError, ValueError) as exc:
        return [], f"invalid PackageManager JSON: {exc}"
    records = [payload] if isinstance(payload, dict) else payload
    if not isinstance(records, list):
        return [], "PackageManager returned an unexpected JSON root"
    return [dict(record) for record in records if isinstance(record, Mapping)], ""

def windows_package_dates_from_records(
    records: Sequence[Mapping[str, Any]],
) -> dict[str, tuple[str, str]]:
    """Retain date evidence, not Store provenance, from the same native enumeration."""
    dates: dict[str, tuple[str, str]] = {}
    conflicting: set[str] = set()
    for record in records:
        full_name = str(record.get("full_name", "")).strip().casefold()
        timestamp, precision = normalize_wall_clock_timestamp(record.get("installed_timestamp", ""))
        if not full_name or len(full_name) > 512 or not timestamp:
            continue
        value = (timestamp, precision)
        if full_name in dates and dates[full_name] != value:
            conflicting.add(full_name)
        dates[full_name] = value
    return {key: value for key, value in dates.items() if key not in conflicting}


def apply_windows_package_dates(
    items: Sequence[UpdateItem], dates: Mapping[str, tuple[str, str]],
) -> int:
    """Join only exact current-account MSIX identities; never alter action policy."""
    applied = 0
    for item in items:
        if (
            item.provider not in {"winget", MICROSOFT_STORE_PROVIDER_KEY}
            or item.scope != "user"
            or not item.package_id.casefold().startswith("msix\\")
        ):
            continue
        evidence = dates.get(item.package_id.split("\\", 1)[1].casefold())
        if evidence is None or (item.installed_timestamp and not item.installed_date_is_estimate):
            continue
        timestamp, precision = evidence
        item.installed_timestamp = timestamp
        item.installed_timestamp_precision = precision
        item.installed_date = dt.datetime.fromisoformat(timestamp).astimezone().date().isoformat()
        item.installed_date_is_estimate = False
        item.installed_date_source = "Windows Package.InstalledDate (installed or last updated)"
        applied += 1
    return applied


def enrich_appx_package_identity(item: UpdateItem) -> UpdateItem:
    """Attach exact AppModel repository evidence to WinGet MSIX inventory rows."""

    if item.provider not in {"winget", MICROSOFT_STORE_PROVIDER_KEY}:
        return item
    manifest_id = item.package_id
    if item.package_id.casefold().startswith("msix\\"):
        location = appx_package_install_location(item.package_id, item.name)
    else:
        # A publisher-qualified mapping cannot override an independently proven EXE.
        if item.scope != "user" or item.installed_technology not in {"", "unknown", "msix"}:
            return item
        registered = registered_launch_package(item.provider, item.package_id, item.current)
        if registered is None:
            return item
        full_name, location = registered
        manifest_id = "MSIX\\" + full_name
    if location is None:
        return item
    item.installed_location = str(location)
    item.installed_technology = "msix"
    if item.scope == "user":
        item.installed_for = "current-user"
    elif item.scope == "machine":
        item.installed_for = "machine"
    if not item.icon_source:
        logo = appx_manifest_logo_path(manifest_id, 256, item.name)
        if logo is not None:
            item.icon_source = str(logo)
    if item.scope == "user" and manifest_id != item.package_id:
        with contextlib.suppress(OSError):
            manifest = location / "AppxManifest.xml"
            stat = manifest.stat()
            item.launch_app_ids = _registered_manifest_launch_ids(
                manifest_id[5:], manifest, stat.st_mtime_ns, stat.st_size,
            )
    if not item.installed_date:
        with contextlib.suppress(OSError, OverflowError, ValueError):
            location_stat = location.stat()
            timestamp = max(location_stat.st_ctime, location_stat.st_mtime)
            item.installed_timestamp = epoch_storage_timestamp(timestamp)
            item.installed_timestamp_precision = "fractional-6"
            item.installed_date = (
                dt.datetime.fromisoformat(item.installed_timestamp)
                .astimezone()
                .date()
                .isoformat()
            )
            item.installed_date_is_estimate = True
            item.installed_date_source = (
                "Windows app package folder activity (approximate; not the original "
                "installation date)"
            )
    item.metadata_sources = tuple(
        dict.fromkeys((*item.metadata_sources, "appx-package-repository"))
    )
    item.metadata_confidence = "proven"
    return item


# ==================== Installed Windows inventory ====================

@dataclasses.dataclass(slots=True)
class WindowsInstalledInventory:
    entries: list[RegistryInstallEntry]

    @classmethod
    def empty(cls) -> WindowsInstalledInventory:
        return cls([])

    @classmethod
    def load(cls) -> WindowsInstalledInventory:
        if os.name != "nt":
            return cls.empty()
        import winreg

        entries: list[RegistryInstallEntry] = []
        roots = (
            (
                winreg.HKEY_CURRENT_USER,
                r"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall",
                "user",
            ),
            (
                winreg.HKEY_LOCAL_MACHINE,
                r"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall",
                "machine",
            ),
            (
                winreg.HKEY_LOCAL_MACHINE,
                r"SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall",
                "machine",
            ),
        )
        for root, subkey, scope in roots:
            try:
                with winreg.OpenKey(root, subkey) as parent:
                    index = 0
                    while True:
                        try:
                            key_name = winreg.EnumKey(parent, index)
                            index += 1
                        except OSError:
                            break
                        entries.extend(cls._read_entry(parent, key_name, scope))
            except OSError:
                continue
        return cls(entries)

    @classmethod
    def _read_entry(cls, parent: Any, key_name: str, scope: str) -> list[RegistryInstallEntry]:
        import winreg

        try:
            with winreg.OpenKey(parent, key_name) as key:
                display_name = str(registry_value(key, "DisplayName", "")).strip()
                display_version = str(registry_value(key, "DisplayVersion", "")).strip()
                if not display_name:
                    return []
                uninstall_string = str(registry_value(key, "UninstallString", "")).strip()
                windows_installer = registry_value(key, "WindowsInstaller", "")
                product_code = key_name if MSI_PRODUCT_CODE_RE.fullmatch(key_name) else ""
                technology = registry_install_technology(
                    key_name, windows_installer, uninstall_string
                )
                install_location = str(registry_value(key, "InstallLocation", "")).strip()
                display_icon = str(registry_value(key, "DisplayIcon", "")).strip()
                if product_code:
                    if not install_location:
                        install_location = msi_product_info(product_code, "InstallLocation")
                    if not display_icon:
                        display_icon = msi_product_info(product_code, "ProductIcon")
                display_icon_path = Path(
                    os.path.expandvars(strip_display_icon_index(display_icon))
                )
                if not display_icon_path.is_file():
                    # Some packages register their install directory as
                    # DisplayIcon even though their uninstaller carries the
                    # actual product artwork (LLVM is a common example).
                    display_icon = local_executable_from_command(uninstall_string)
                installed_date = normalized_registry_install_date(
                    registry_value(key, "InstallDate", "")
                )
                installed_date_source = (
                    "Windows uninstall InstallDate (installed or last serviced)"
                    if installed_date
                    else ""
                )
                if not installed_date and technology == "msi" and product_code:
                    installed_date = normalized_registry_install_date(
                        msi_product_info(product_code, "InstallDate")
                    )
                    if installed_date:
                        installed_date_source = (
                            "Windows Installer InstallDate (last serviced; original install "
                            "if never serviced)"
                        )
                registration_changed_at = registry_key_last_write_timestamp(key)
                registration_changed_date = ""
                if registration_changed_at:
                    with contextlib.suppress(ValueError):
                        registration_changed_date = (
                            dt.datetime.fromisoformat(registration_changed_at)
                            .astimezone()
                            .date()
                            .isoformat()
                        )
                return [
                    RegistryInstallEntry(
                        display_name=display_name,
                        display_version=display_version,
                        scope=scope,
                        technology=technology,
                        install_location=install_location,
                        display_icon=display_icon,
                        uninstall_command=uninstall_string,
                        uninstall_key=key_name,
                        product_code=product_code,
                        estimated_size_kb=registry_estimated_size_kb(
                            registry_value(key, "EstimatedSize", None)
                        ),
                        installed_date=installed_date,
                        installed_timestamp_precision=("date" if installed_date else ""),
                        installed_date_source=installed_date_source,
                        registration_changed_date=registration_changed_date,
                        registration_changed_at=registration_changed_at,
                    )
                ]
        except OSError:
            return []

    def matches(self, name: str, version: str, scope: str) -> list[RegistryInstallEntry]:
        if name.casefold().startswith("arp\\"):
            parts = name.split("\\", 3)
            if len(parts) == 4:
                encoded_scope = "machine" if parts[1].casefold() == "machine" else "user"
                encoded_key = parts[3].casefold()
                exact = [
                    entry
                    for entry in self.entries
                    if entry.scope == encoded_scope
                    and entry.uninstall_key.casefold() == encoded_key
                ]
                if exact:
                    return exact
        folded_name = normalized_package_name(name)
        folded_version = version.casefold()
        candidate_scopes = {scope} if scope in {"user", "machine"} else {"user", "machine"}
        return [
            entry
            for entry in self.entries
            if entry.scope in candidate_scopes
            and entry.display_version.casefold() == folded_version
            and normalized_package_name(entry.display_name) == folded_name
        ]

    def enrich(self, item: UpdateItem) -> UpdateItem:
        matches = self.matches(item.package_id, item.current, item.scope)
        if not matches:
            matches = self.matches(item.name, item.current, item.scope)
        if not matches:
            return enrich_appx_package_identity(item)
        scopes = sorted({entry.scope for entry in matches})
        technologies = sorted({entry.technology for entry in matches if entry.technology})
        locations = sorted({entry.install_location for entry in matches if entry.install_location})
        display_icons = sorted({entry.display_icon for entry in matches if entry.display_icon})
        product_codes = sorted({entry.product_code for entry in matches if entry.product_code})
        estimated_sizes = sorted(
            {entry.estimated_size_kb for entry in matches if entry.estimated_size_kb}
        )
        dated_entries = sorted(
            (entry for entry in matches if entry.installed_date),
            key=lambda entry: (
                entry.installed_date,
                wall_clock_order_key(entry.installed_timestamp),
            ),
        )
        registration_dates = sorted(
            {
                entry.registration_changed_date
                for entry in matches
                if entry.registration_changed_date
            }
        )
        registration_timestamps = sorted(
            {
                entry.registration_changed_at
                for entry in matches
                if entry.registration_changed_at
            },
            key=lambda value: dt.datetime.fromisoformat(value).timestamp(),
        )
        if registration_timestamps:
            item.installed_registration_changed_at = registration_timestamps[-1]
            item.installed_registration_changed_at_precision = "fractional-6"
        item.installed_for = (
            "mixed"
            if len(scopes) > 1
            else "current-user"
            if scopes == ["user"]
            else "machine"
            if scopes == ["machine"]
            else "unknown"
        )
        item.installed_technology = (
            technologies[0] if len(technologies) == 1 else "mixed" if technologies else "unknown"
        )
        item.installed_location = locations[0] if len(locations) == 1 else ""
        item.icon_source = display_icons[0] if len(display_icons) == 1 else ""
        item.product_codes = tuple(product_codes)
        item.installed_size_kb = estimated_sizes[0] if len(estimated_sizes) == 1 else None
        # When duplicate registrations match, the newest explicit Windows date
        # is the most useful representation of the currently serviced install.
        if dated_entries:
            newest = dated_entries[-1]
            item.installed_date = newest.installed_date
            item.installed_timestamp = newest.installed_timestamp
            item.installed_timestamp_precision = (
                newest.installed_timestamp_precision
                or ("date" if newest.installed_date else "")
            )
            item.installed_date_source = newest.installed_date_source
            item.installed_date_is_estimate = False
        elif registration_dates:
            item.installed_date = registration_dates[-1]
            item.installed_timestamp = (
                registration_timestamps[-1] if registration_timestamps else ""
            )
            item.installed_timestamp_precision = (
                "fractional-6" if item.installed_timestamp else "date"
            )
            item.installed_date_source = (
                "Windows uninstall registration last changed (approximate; not the "
                "original installation date)"
            )
            item.installed_date_is_estimate = True
        item.metadata_sources = ("arp-uninstall",)
        item.metadata_confidence = "proven"
        return enrich_appx_package_identity(item)


def registry_value(key: Any, name: str, default: Any = "") -> Any:
    import winreg

    try:
        value, _value_type = winreg.QueryValueEx(key, name)
        return value
    except OSError:
        return default


def valid_package_id(value: str) -> bool:
    """Accept provider identifiers as inert data, never path-like traversal."""

    if not value or len(value) > 240 or not SAFE_PACKAGE_ID_RE.fullmatch(value):
        return False
    if ".." in value or value.endswith(("/", ".")):
        return False
    # Preserve legitimate scoped package IDs such as ``@scope/package`` while
    # rejecting empty and explicit current/parent path segments.
    return all(segment not in {"", ".", ".."} for segment in value.split("/"))


def valid_inventory_id(value: str) -> bool:
    return bool(
        value
        and len(value) <= 320
        and "…" not in value
        and not any(ord(character) < 32 for character in value)
    )


def valid_version(value: str) -> bool:
    """Accept exact registry versions that remain data across Windows command bridges."""
    return bool(value and len(value) <= 128 and SAFE_VERSION_RE.fullmatch(value))


def valid_provider_source(value: str) -> bool:
    """Accept a conservative named package repository, never a URI or expression."""
    return bool(value and len(value) <= 128 and SAFE_PROVIDER_SOURCE_RE.fullmatch(value))


def treeview_wheel_rows_per_notch(binding: str) -> int:
    """Recognize tested Windows defaults; leave unfamiliar Tk/custom bindings alone."""
    return {
        "%W yview scroll [expr {-%D / 120}] units": 1,  # Tk 8.6
        "tk::MouseWheel %W y %D -40.0": 3,  # Tk 9.0
    }.get(" ".join(binding.split()), 0)


def accumulated_wheel_rows(delta: int, remainder: int, rows_per_notch: int) -> tuple[int, int]:
    """Conserve signed Windows wheel input at whole-row granularity, without floats."""
    total = remainder + delta * rows_per_notch
    steps = (abs(total) // 120) * (1 if total >= 0 else -1)
    return -steps, total - steps * 120


def search_match_rank(query: str, ranked_fields: Sequence[tuple[int, str]]) -> tuple[int, int]:
    """Rank a substring match by field priority, then by earliest occurrence."""
    folded_query = normalize_search_text(query)
    if not folded_query:
        return (0, 0)
    best = (999, 999_999)
    for priority, value in ranked_fields:
        if (priority, 0) >= best:
            continue
        normalized_value = normalize_search_text(str(value))
        position = normalized_value.find(folded_query)
        if position >= 0:
            best = min(best, (priority, position))
    return best


@functools.lru_cache(maxsize=128)
def parse_package_filter(query: str) -> tuple[str, tuple[tuple[str, str], ...]]:
    """Optional whitespace-delimited field filters; all remaining text stays a phrase."""

    terms: list[str] = []
    filters: list[tuple[str, str]] = []
    for token in query.split():
        key, separator, value = token.partition(":")
        if separator and key.casefold() in {"provider", "scope", "is"}:
            key, value = key.casefold(), value.casefold()
            if key == "provider":
                value = {
                    "store": "msstore", "microsoft-store": "msstore",
                    "dotnet": "dotnet-tool", ".net": "dotnet-tool", "uv": "uv-tool",
                    "powershell7": "powershell", "choco": "chocolatey",
                }.get(value, value)
            filters.append((key, value))
        else:
            terms.append(token)
    return (" ".join(terms) if filters else query), tuple(filters)


def package_filter_matches(
    item: UpdateItem,
    filters: Sequence[tuple[str, str]],
    attempt_holds: Mapping[str, Any],
) -> bool:
    """Filter current evidence only; this never changes selection or action eligibility."""

    for key, value in filters:
        if not value:
            return False
        if key == "provider":
            if value != installed_channel_display_label(item, item.provider).casefold():
                return False
        elif key == "scope":
            if value != item.scope.casefold():
                return False
        elif key == "is":
            if value == "admin":
                matched = item.requires_admin
            elif value == "selected":
                matched = item.selected
            elif value == "portable":
                matched = item.provider == PORTABLE_PROVIDER_KEY
            elif value == "held":
                matched = attempt_record_matches_current_strategy(attempt_holds.get(item.candidate_key))
            else:
                return False
            if not matched:
                return False
        else:
            return False
    return True


@functools.lru_cache(maxsize=8192)
def normalize_search_text(value: str) -> str:
    """Normalize user-facing search text, not package IDs or commands.

    Quick search should tolerate punctuation and casing in display labels:
    `.NET global tools` and `net global tools` should match the same provider
    label. This does not alter package IDs or command safety checks.
    """

    return " ".join(re.findall(r"[a-z0-9]+", value.casefold()))


_SEMANTIC_VERSION_RE = re.compile(
    r"^[vV]?(?P<release>\d+(?:\.\d+){0,3})"
    r"(?:-(?P<prerelease>[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?"
    r"(?:\+[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?$"
)


def _semantic_version_parts(
    value: str,
) -> tuple[tuple[int, ...], tuple[tuple[bool, int | str], ...] | None] | None:
    """Parse the conservative SemVer/NuGet subset used for update ordering."""

    match = _SEMANTIC_VERSION_RE.fullmatch(value.strip())
    if not match:
        return None
    release = [int(part) for part in match.group("release").split(".")]
    while len(release) > 1 and release[-1] == 0:
        release.pop()
    prerelease_text = match.group("prerelease")
    if prerelease_text is None:
        return tuple(release), None
    prerelease: list[tuple[bool, int | str]] = []
    for identifier in prerelease_text.split("."):
        prerelease.append(
            (True, int(identifier))
            if identifier.isdecimal()
            else (False, identifier.casefold())
        )
    return tuple(release), tuple(prerelease)


def compare_semantic_versions(left: str, right: str) -> int | None:
    """Compare a bounded SemVer/NuGet pair, or return None when syntax is uncertain."""

    left_parts = _semantic_version_parts(left)
    right_parts = _semantic_version_parts(right)
    if left_parts is None or right_parts is None:
        return None
    left_release, left_prerelease = left_parts
    right_release, right_prerelease = right_parts
    width = max(len(left_release), len(right_release))
    left_padded = left_release + (0,) * (width - len(left_release))
    right_padded = right_release + (0,) * (width - len(right_release))
    if left_padded != right_padded:
        return 1 if left_padded > right_padded else -1
    if left_prerelease is None or right_prerelease is None:
        if left_prerelease is right_prerelease:
            return 0
        return 1 if left_prerelease is None else -1
    for left_identifier, right_identifier in zip(left_prerelease, right_prerelease):
        if left_identifier == right_identifier:
            continue
        left_numeric, left_value = left_identifier
        right_numeric, right_value = right_identifier
        if left_numeric != right_numeric:
            return -1 if left_numeric else 1
        return 1 if left_value > right_value else -1
    if len(left_prerelease) == len(right_prerelease):
        return 0
    return 1 if len(left_prerelease) > len(right_prerelease) else -1


def latest_nuget_listed_version(package_id: str) -> tuple[str, str]:
    """Return the exact package's latest listed stable NuGet version."""
    if not valid_package_id(package_id):
        return "", f"unsafe NuGet package id: {package_id!r}"
    query = urllib.parse.urlencode(
        {
            "q": f"packageid:{package_id}",
            "prerelease": "false",
            "semVerLevel": "2.0.0",
            "take": "20",
        }
    )
    request = urllib.request.Request(
        f"https://azuresearch-usnc.nuget.org/query?{query}",
        headers={"User-Agent": f"{APP_NAME}/{APP_VERSION}"},
    )
    try:
        with urllib.request.urlopen(request, timeout=15) as response:
            payload = json.loads(response.read(2_000_000).decode("utf-8", errors="replace"))
    except (OSError, urllib.error.URLError, json.JSONDecodeError) as exc:
        return "", f"NuGet latest-version lookup failed for {package_id}: {exc}"
    data = payload.get("data", []) if isinstance(payload, dict) else []
    if not isinstance(data, list) or len(data) > 20:
        return "", f"NuGet search payload for {package_id} was not a bounded result list"
    exact_hits = [
        entry
        for entry in data
        if isinstance(entry, dict)
        and str(entry.get("id", "")).strip().casefold() == package_id.casefold()
    ]
    if len(exact_hits) != 1:
        return "", f"NuGet search found no unique exact listed package for {package_id}"
    version = str(exact_hits[0].get("version", "")).strip()
    version_parts = _semantic_version_parts(version)
    if (
        not valid_version(version)
        or version_parts is None
        or version_parts[1] is not None
    ):
        return "", f"NuGet search returned an unsafe or unorderable version for {package_id}"
    return version, ""


def latest_pypi_version(package_id: str) -> tuple[str, str]:
    """Return latest PyPI version plus a warning string."""
    if not valid_package_id(package_id):
        return "", f"unsafe PyPI package id: {package_id!r}"
    quoted = urllib.parse.quote(package_id, safe="")
    request = urllib.request.Request(
        f"https://pypi.org/pypi/{quoted}/json",
        headers={"User-Agent": f"{APP_NAME}/{APP_VERSION}"},
    )
    try:
        with urllib.request.urlopen(request, timeout=15) as response:
            payload = json.loads(response.read(2_000_000).decode("utf-8", errors="replace"))
    except (OSError, urllib.error.URLError, json.JSONDecodeError) as exc:
        return "", f"PyPI latest-version lookup failed for {package_id}: {exc}"
    version = str(payload.get("info", {}).get("version", "")).strip()
    if not valid_version(version):
        return (
            "",
            f"PyPI latest-version lookup returned unsafe version for {package_id}: {version!r}",
        )
    return version, ""


def sentinel_json_payload(output: str, begin: str, end: str) -> Any:
    """Extract the final explicitly delimited JSON payload from command chatter."""
    lines = output.splitlines()
    starts = [index for index, line in enumerate(lines) if line.strip() == begin]
    if not starts:
        raise ValueError(f"missing {begin} marker")
    start = starts[-1] + 1
    finishes = [index for index in range(start, len(lines)) if lines[index].strip() == end]
    if not finishes:
        raise ValueError(f"missing {end} marker")
    payload = "\n".join(lines[start : finishes[0]]).strip()
    if not payload:
        raise ValueError("delimited JSON payload is empty")
    return json.loads(payload)


def utc_now_iso() -> str:
    """Return an unambiguous wall-clock observation with full Python precision."""

    return dt.datetime.now(dt.UTC).isoformat(timespec="microseconds")


ISO_WALL_CLOCK_RE = re.compile(
    r"^(?P<date>\d{4}-\d{2}-\d{2})"
    r"(?:[T ](?P<hour>\d{2}):(?P<minute>\d{2}):(?P<second>\d{2})"
    r"(?:\.(?P<fraction>\d{1,6}))?"
    r"(?P<zone>Z|[+-]\d{2}:?\d{2})?)?$"
)


def normalize_wall_clock_timestamp(value: Any) -> tuple[str, str]:
    """Normalize an ISO wall-clock value without claiming unavailable precision.

    Fractional values use a six-digit storage representation while the returned
    precision label remembers how many digits the source actually supplied.
    Date-only and whole-second sources stay date-only and whole-second.
    """

    raw = str(value).strip()
    match = ISO_WALL_CLOCK_RE.fullmatch(raw)
    if match is None:
        return "", ""
    if match.group("hour") is None:
        try:
            return dt.date.fromisoformat(raw).isoformat(), "date"
        except ValueError:
            return "", ""
    parseable = raw[:-1] + "+00:00" if raw.endswith("Z") else raw
    try:
        observed = dt.datetime.fromisoformat(parseable)
    except ValueError:
        return "", ""
    fraction = match.group("fraction") or ""
    precision = "second" if not fraction else f"fractional-{len(fraction)}"
    timespec = "seconds" if not fraction else "microseconds"
    return observed.isoformat(timespec=timespec), precision


def wall_clock_timestamp_matches_precision(value: str, precision: str) -> bool:
    """Validate canonical storage plus its original source-precision label."""

    normalized, inferred = normalize_wall_clock_timestamp(value)
    if not normalized or normalized != value:
        return False
    if precision == inferred:
        return True
    match = re.fullmatch(r"fractional-([1-6])", precision)
    lexical = ISO_WALL_CLOCK_RE.fullmatch(value)
    if match is None or lexical is None or inferred != "fractional-6":
        return False
    digits = int(match.group(1))
    fraction = lexical.group("fraction") or ""
    return len(fraction) == 6 and set(fraction[digits:]) <= {"0"}


def wall_clock_order_key(value: Any) -> float:
    """Return an absolute ordering key for ISO timestamps with differing offsets."""

    normalized, precision = normalize_wall_clock_timestamp(value)
    if not normalized:
        return float("-inf")
    try:
        if precision == "date":
            observed = dt.datetime.combine(
                dt.date.fromisoformat(normalized), dt.time(), tzinfo=dt.UTC
            )
        else:
            observed = dt.datetime.fromisoformat(normalized)
            if observed.tzinfo is None:
                observed = observed.astimezone()
        return observed.timestamp()
    except (OSError, OverflowError, ValueError):
        return float("-inf")


def valid_wall_clock_instant(value: Any, *, require_timezone: bool = True) -> bool:
    normalized, precision = normalize_wall_clock_timestamp(value)
    if not normalized or precision == "date":
        return False
    try:
        observed = dt.datetime.fromisoformat(normalized)
    except ValueError:
        return False
    return observed.tzinfo is not None or not require_timezone


def datetime_storage_timestamp(value: dt.datetime) -> str:
    """Serialize an application-owned observation as aware ISO 8601 microseconds."""

    if value.tzinfo is None:
        value = value.astimezone()
    return value.isoformat(timespec="microseconds")


def epoch_storage_timestamp(value: int | float) -> str:
    """Serialize an OS epoch timestamp in UTC without dropping sub-second data."""

    try:
        numeric = float(value)
        if not math.isfinite(numeric):
            return ""
        return dt.datetime.fromtimestamp(numeric, tz=dt.UTC).isoformat(
            timespec="microseconds"
        )
    except (OSError, OverflowError, TypeError, ValueError):
        return ""


def _rounded_display_datetime(value: dt.datetime) -> dt.datetime:
    """Round one datetime to a centisecond without reducing stored precision."""

    original_timezone = value.tzinfo
    working = value.astimezone(dt.UTC) if original_timezone is not None else value
    whole_second = working.replace(microsecond=0)
    centiseconds = (working.microsecond + 5_000) // 10_000
    if centiseconds == 100:
        rounded = whole_second + dt.timedelta(seconds=1)
    else:
        rounded = whole_second.replace(microsecond=centiseconds * 10_000)
    return rounded.astimezone(original_timezone) if original_timezone is not None else rounded


def datetime_display_timestamp(value: dt.datetime) -> str:
    """Render an ISO timestamp rounded to exactly two fractional digits."""

    rounded = _rounded_display_datetime(value)
    rendered = rounded.isoformat(timespec="microseconds")
    return re.sub(r"(?<=\d{2}:\d{2}:\d{2}\.\d{2})\d{4}", "", rendered, count=1)


def wall_clock_display_timestamp(value: Any) -> str:
    """Render stored ISO wall-clock evidence at presentation precision."""

    normalized, precision = normalize_wall_clock_timestamp(value)
    if precision == "date":
        return normalized
    try:
        return datetime_display_timestamp(dt.datetime.fromisoformat(normalized))
    except (OSError, OverflowError, TypeError, ValueError):
        return str(value) if value is not None else ""


def clock_display_time(value: dt.datetime, *, twelve_hour: bool = False) -> str:
    """Render a compact clock time rounded to exactly one centisecond."""

    if value.tzinfo is not None:
        value = value.astimezone()
    rounded = _rounded_display_datetime(value)
    pattern = "%I:%M:%S" if twelve_hour else "%H:%M:%S"
    rendered = rounded.strftime(pattern)
    if twelve_hour:
        rendered = rendered.lstrip("0")
    rendered += f".{rounded.microsecond // 10_000:02d}"
    return rendered + rounded.strftime(" %p") if twelve_hour else rendered


def wall_clock_precision_label(precision: str) -> str:
    labels = {
        "date": "date only",
        "second": "whole second",
        "fractional-1": "0.1 second",
        "fractional-2": "0.01 second",
        "fractional-3": "millisecond",
        "fractional-4": "0.1 millisecond",
        "fractional-5": "10 microseconds",
        "fractional-6": "microsecond",
    }
    return labels.get(precision, precision)


def local_observation_time(value: str, precision: str = "") -> str:
    """Render persisted ISO evidence locally, rounded to a centisecond."""

    normalized, inferred_precision = normalize_wall_clock_timestamp(value)
    precision = precision or inferred_precision
    if precision == "date":
        return normalized or value or "(not recorded)"
    try:
        observed = dt.datetime.fromisoformat(normalized or value)
        if observed.tzinfo is not None:
            observed = observed.astimezone()
        observed = _rounded_display_datetime(observed)
        rendered = observed.strftime("%Y-%m-%d %I:%M:%S")
        rendered += f".{observed.microsecond // 10_000:02d}"
        suffix = observed.strftime(" %p %Z").rstrip()
        return rendered + suffix
    except (OSError, OverflowError, TypeError, ValueError):
        return value or "(not recorded)"


def normalized_exit_code(returncode: int) -> int:
    """Represent signed HRESULT-style process results as their unsigned DWORD."""
    return returncode & 0xFFFFFFFF if returncode < 0 else returncode


def exit_code_hex(returncode: int) -> str:
    return f"0x{normalized_exit_code(returncode):08X}"


def _redact_sensitive_text_full(redacted: str) -> str:
    """Apply every credential and user-path redaction rule."""

    profile = os.environ.get("USERPROFILE", "").rstrip("\\/")
    if profile:
        redacted = re.sub(re.escape(profile), "%USERPROFILE%", redacted, flags=re.IGNORECASE)
    redacted = re.sub(
        r"(?i)\b([A-Z]:\\Users\\)(?!Public\\|Default\\|Default User\\)[^\\\r\n]+",
        r"\1[USER]",
        redacted,
    )
    computer_name = os.environ.get("COMPUTERNAME", "").strip()
    if computer_name:
        escaped_name = re.escape(computer_name)
        redacted = re.sub(
            rf"(?i)(\\\\){escaped_name}(?=\\)",
            r"\1[COMPUTER]",
            redacted,
        )
        if len(computer_name) >= 4:
            redacted = re.sub(
                rf"(?i)(?<![A-Z0-9_-]){escaped_name}(?![A-Z0-9_-])",
                "[COMPUTER]",
                redacted,
            )
    redacted = URL_USERINFO_RE.sub(r"\1[REDACTED]@", redacted)
    redacted = AUTH_SCHEME_RE.sub(r"\1 [REDACTED]", redacted)
    redacted = SENSITIVE_OPTION_RE.sub(r"\1[REDACTED]", redacted)
    return SENSITIVE_ASSIGNMENT_RE.sub(r"\1[REDACTED]", redacted)


def redact_sensitive_text(value: str) -> str:
    """Remove common credentials while preserving diagnostics for later analysis."""

    redacted = str(value)
    # Every current rule requires whitespace or one of these delimiter/path
    # characters. Keep this superset synchronized if a future redactor can
    # match a plain alphanumeric string.
    if not redacted or REDACTION_TRIGGER_RE.search(redacted) is None:
        return redacted
    return _redact_sensitive_text_full(redacted)


def redact_log_value(value: Any, *, key: str = "") -> Any:
    folded_key = key.casefold().replace("-", "_")
    if folded_key in PRE_REDACTED_STRING_KEYS and isinstance(value, str):
        return value
    if folded_key in PRE_REDACTED_SEQUENCE_KEYS and isinstance(value, (list, tuple)):
        return list(value)
    if any(
        marker in folded_key
        for marker in (
            "access_key",
            "api_key",
            "auth_key",
            "authkey",
            "authorization",
            "client_secret",
            "cookie",
            "credential",
            "password",
            "private_key",
            "secret",
            "token",
        )
    ):
        return "[REDACTED]"
    if isinstance(value, str):
        return redact_sensitive_text(value)
    if isinstance(value, Path):
        return redact_sensitive_text(str(value))
    if isinstance(value, dict):
        return {
            str(field): redact_log_value(field_value, key=str(field))
            for field, field_value in value.items()
        }
    if isinstance(value, (list, tuple, set)):
        return [redact_log_value(entry, key=key) for entry in value]
    if value is None or isinstance(value, (bool, int, float)):
        return value
    return redact_sensitive_text(str(value))


def redact_command_parts(parts: Sequence[str]) -> list[str]:
    """Redact both inline secrets and the argument following a sensitive option."""
    redacted: list[str] = []
    redact_next = False
    for part in parts:
        if redact_next:
            redacted.append("[REDACTED]")
            redact_next = False
            continue
        safe_part = redact_sensitive_text(str(part))
        redacted.append(safe_part)
        redact_next = bool(SENSITIVE_OPTION_NAME_RE.fullmatch(str(part)))
    return redacted


def bounded_diagnostic_output(output: str) -> dict[str, Any]:
    """Redact output and retain useful head/tail context under a receipt-safe bound."""
    redacted = redact_sensitive_text(output)
    original_chars = len(redacted)
    digest = hashlib.sha256(redacted.encode("utf-8", errors="replace")).hexdigest()
    if original_chars <= MAX_DIAGNOSTIC_OUTPUT_CHARS:
        stored = redacted
        truncated = False
        omitted = 0
    else:
        tail_chars = MAX_DIAGNOSTIC_OUTPUT_CHARS - DIAGNOSTIC_OUTPUT_HEAD_CHARS
        omitted = original_chars - MAX_DIAGNOSTIC_OUTPUT_CHARS
        stored = (
            redacted[:DIAGNOSTIC_OUTPUT_HEAD_CHARS]
            + f"\n\n[WinDevPilot omitted {omitted} redacted output characters]\n\n"
            + redacted[-tail_chars:]
        )
        truncated = True
    return {
        "output": stored,
        "output_chars": original_chars,
        "output_redacted_sha256": digest,
        "output_truncated": truncated,
        "output_omitted_chars": omitted,
    }


def winget_installer_log_paths(output: str) -> list[Path]:
    """Extract the diagnostic-log paths WinGet explicitly reports."""
    paths: list[Path] = []
    seen: set[str] = set()
    for match in WINGET_INSTALLER_LOG_RE.finditer(clean_output(output)):
        raw_path = match.group("path").strip().strip('"')
        path = Path(os.path.expandvars(raw_path))
        folded = os.path.normcase(str(path))
        if folded not in seen:
            paths.append(path)
            seen.add(folded)
        if len(paths) >= MAX_RELATED_INSTALLER_LOGS:
            break
    return paths


def _path_is_within(path: Path, root: Path) -> bool:
    try:
        resolved_path = os.path.normcase(str(path.resolve(strict=False)))
        resolved_root = os.path.normcase(str(root.resolve(strict=False)))
        return os.path.commonpath((resolved_path, resolved_root)) == resolved_root
    except (OSError, ValueError):
        return False


def _sha256_file(path: Path) -> str:
    digest = hashlib.sha256()
    with path.open("rb") as stream:
        for chunk in iter(lambda: stream.read(1024 * 1024), b""):
            digest.update(chunk)
    return digest.hexdigest()


def _read_related_installer_log(path: Path) -> tuple[str, int]:
    size = path.stat().st_size
    with path.open("rb") as stream:
        if size <= MAX_RELATED_INSTALLER_LOG_READ_BYTES:
            return clean_output(decode_console_output(stream.read())), 0
        head_size = MAX_RELATED_INSTALLER_LOG_READ_BYTES * 2 // 5
        tail_size = MAX_RELATED_INSTALLER_LOG_READ_BYTES - head_size
        head = stream.read(head_size)
        stream.seek(-tail_size, os.SEEK_END)
        tail = stream.read(tail_size)
    omitted = size - len(head) - len(tail)
    text = (
        clean_output(decode_console_output(head))
        + f"\n\n[WinDevPilot omitted {omitted} installer-log bytes]\n\n"
        + clean_output(decode_console_output(tail))
    )
    return text, omitted


def collect_winget_installer_logs(result: CommandResult) -> list[dict[str, Any]]:
    """Copy bounded WinGet child-installer logs into the shareable receipt."""
    local_app_data = os.environ.get("LOCALAPPDATA")
    if not local_app_data:
        return []
    allowed_root = (
        Path(local_app_data)
        / "Packages"
        / "Microsoft.DesktopAppInstaller_8wekyb3d8bbwe"
        / "LocalState"
        / "DiagOutputDir"
    )
    logs: list[dict[str, Any]] = []
    for path in winget_installer_log_paths(result.output):
        if not path.is_absolute() or not _path_is_within(path, allowed_root):
            continue
        try:
            content, read_omitted_bytes = _read_related_installer_log(path)
            stat = path.stat()
            logs.append(
                {
                    "path": redact_sensitive_text(str(path)),
                    "size_bytes": stat.st_size,
                    "modified_at": epoch_storage_timestamp(stat.st_mtime),
                    "file_sha256": _sha256_file(path),
                    "read_omitted_bytes": read_omitted_bytes,
                    **bounded_diagnostic_output(content),
                }
            )
        except OSError as exc:
            logs.append(
                {
                    "path": redact_sensitive_text(str(path)),
                    "read_error": redact_sensitive_text(str(exc)),
                }
            )
    return logs


def _winget_scope_mismatch_from_text(text: str) -> tuple[str, str] | None:
    match = WINGET_SCOPE_MISMATCH_RE.search(clean_output(text))
    if not match:
        return None
    return match.group("installer").title(), match.group("installed").title()


def winget_scope_mismatch_evidence(result: CommandResult) -> tuple[str, str] | None:
    """Return a proven installer/installed scope conflict from this WinGet attempt.

    WinGet prints only a generic no-applicable message to stdout, while
    ``--verbose-logs`` records the decisive ``Machine != User`` reason in its
    own diagnostic log. Match that log by the completed child process ID; never
    borrow evidence from another concurrent scan or package operation.
    """

    if normalized_exit_code(result.returncode) not in WINGET_NOT_APPLICABLE_CODES:
        return None
    direct = _winget_scope_mismatch_from_text(result.output)
    if direct is not None:
        return direct
    if os.name != "nt" or not result.process_id:
        return None
    local_app_data = os.environ.get("LOCALAPPDATA")
    if not local_app_data:
        return None
    diagnostic_root = (
        Path(local_app_data)
        / "Packages"
        / "Microsoft.DesktopAppInstaller_8wekyb3d8bbwe"
        / "LocalState"
        / "DiagOutputDir"
    )
    process_marker = f"Process: winget.exe[{result.process_id}]".casefold()
    candidates: list[tuple[float, Path]] = []
    try:
        for path in diagnostic_root.glob("WinGet-*.log"):
            try:
                candidates.append((path.stat().st_mtime, path))
            except OSError:
                continue
    except OSError:
        return None
    for _modified, path in heapq.nlargest(32, candidates, key=lambda entry: entry[0]):
        try:
            with path.open("rb") as stream:
                head = stream.read(8192)
                head_text = decode_console_output(head)
                if process_marker not in head_text.casefold():
                    continue
                remaining = max(0, MAX_RELATED_INSTALLER_LOG_READ_BYTES - len(head))
                content = head_text + decode_console_output(stream.read(remaining))
        except OSError:
            continue
        mismatch = _winget_scope_mismatch_from_text(content)
        if mismatch is not None:
            return mismatch
        # Process IDs identify one exact WinGet invocation. Once matched, no
        # other log may contribute evidence for this result.
        return None
    return None


def annotate_winget_scope_mismatch(result: CommandResult) -> tuple[str, str] | None:
    mismatch = winget_scope_mismatch_evidence(result)
    if mismatch is None:
        return None
    installer_scope, installed_scope = mismatch
    evidence = (
        "WinGet diagnostic: Installer scope does not match currently installed scope: "
        f"{installer_scope} != {installed_scope}"
    )
    if evidence.casefold() not in result.output.casefold():
        result.output = "\n".join(part for part in (result.output.strip(), evidence) if part)
    return mismatch


def winget_existing_install_permission_failure_path(result: CommandResult) -> str:
    """Return the exact blocked path for WinGet's portable-package ACL failure."""
    if normalized_exit_code(result.returncode) != 0x8A150003:
        return ""
    match = WINGET_CANONICAL_ACCESS_DENIED_RE.search(clean_output(result.output))
    if not match:
        return ""
    raw_path = os.path.expandvars(match.group("path").strip())
    path = PureWindowsPath(raw_path)
    return str(path) if path.is_absolute() else ""


_FILE_BLOCKER_PROBE_SLOT = threading.BoundedSemaphore(1)


def failed_file_access_path(output: str) -> str:
    """Accept an exact quoted local file on an explicit access/lock error line.

    Do not infer targets from package names, expand variables, inspect folders,
    or send UNC/device paths to Restart Manager. Unrecognized transcripts simply
    retain their original installer guidance.
    """
    for line in clean_output(output).splitlines():
        if len(line) > 8192 or not re.search(
            r"(?i)access (?:is )?denied|permission denied|sharing violation|"
            r"being used by another process|\b(?:EPERM|EBUSY)\b", line
        ):
            continue
        for match in re.finditer(
            r'''(?P<quote>["'])(?P<path>[A-Za-z]:[\\/][^\r\n]{1,4096}?)(?P=quote)''', line
        ):
            path = PureWindowsPath(match.group("path"))
            if (
                path.is_absolute() and len(path.drive) == 2
                and not any(c in str(path)[2:] for c in ':*?<>|"\x00')
                and not any(ord(c) < 32 for c in str(path))
                and ".." not in path.parts
            ):
                return str(path)
    return ""


def _windows_file_users(path: str) -> list[dict[str, Any]]:
    """Query one file, without shutdown/restart calls or privilege escalation.

    Runs only in the bounded failure-diagnostic worker. All native buffers have
    explicit capacities; every successfully opened RM session is ended.
    """
    from ctypes import wintypes

    class UniqueProcess(ctypes.Structure):
        _fields_ = [("pid", wintypes.DWORD), ("started", wintypes.FILETIME)]

    class ProcessInfo(ctypes.Structure):
        _fields_ = [
            ("process", UniqueProcess), ("name", wintypes.WCHAR * 256),
            ("service", wintypes.WCHAR * 64), ("kind", ctypes.c_int),
            ("status", wintypes.ULONG), ("session", wintypes.DWORD),
            ("restartable", wintypes.BOOL),
        ]

    rm = ctypes.WinDLL("rstrtmgr", use_last_error=True)
    rm.RmStartSession.argtypes = [ctypes.POINTER(wintypes.DWORD), wintypes.DWORD, wintypes.LPWSTR]
    rm.RmStartSession.restype = wintypes.DWORD
    rm.RmRegisterResources.argtypes = [
        wintypes.DWORD, wintypes.UINT, ctypes.POINTER(wintypes.LPCWSTR),
        wintypes.UINT, ctypes.POINTER(UniqueProcess), wintypes.UINT,
        ctypes.POINTER(wintypes.LPCWSTR),
    ]
    rm.RmRegisterResources.restype = wintypes.DWORD
    rm.RmGetList.argtypes = [
        wintypes.DWORD, ctypes.POINTER(wintypes.UINT), ctypes.POINTER(wintypes.UINT),
        ctypes.POINTER(ProcessInfo), ctypes.POINTER(wintypes.DWORD),
    ]
    rm.RmGetList.restype = wintypes.DWORD
    rm.RmEndSession.argtypes = [wintypes.DWORD]
    rm.RmEndSession.restype = wintypes.DWORD
    session = wintypes.DWORD()
    key = ctypes.create_unicode_buffer(33)
    error = rm.RmStartSession(ctypes.byref(session), 0, key)
    if error:
        raise ctypes.WinError(error)
    try:
        files = (wintypes.LPCWSTR * 1)(path)
        error = rm.RmRegisterResources(session, 1, files, 0, None, 0, None)
        if error:
            raise ctypes.WinError(error)
        # A bounded retry tolerates processes appearing between the two calls.
        capacity = 0
        for _ in range(3):
            needed, count, reasons = wintypes.UINT(), wintypes.UINT(capacity), wintypes.DWORD()
            buffer = (ProcessInfo * capacity)() if capacity else None
            error = rm.RmGetList(
                session, ctypes.byref(needed), ctypes.byref(count), buffer, ctypes.byref(reasons)
            )
            if error == 234 and 0 < needed.value <= 64:  # ERROR_MORE_DATA
                capacity = needed.value
                continue
            if error:
                raise ctypes.WinError(error)
            if count.value > capacity:
                raise ValueError("Restart Manager returned an invalid process count")
            return [
                {
                    "pid": info.process.pid,
                    "started_ticks": (info.process.started.dwHighDateTime << 32)
                    | info.process.started.dwLowDateTime,
                    "name": info.name, "service": info.service, "kind": info.kind,
                }
                for info in (buffer or ())[:count.value]
            ]
        raise OSError("Restart Manager process list kept changing")
    finally:
        rm.RmEndSession(session)


def _windows_blocker_process_context(users: list[dict[str, Any]]) -> list[dict[str, Any]]:
    """Add limited-query image names and a short, creation-time-checked ancestry.

    Parents provide launch context, not additional proof of a file lock. Never
    collect command lines, environment, or unrelated process details.
    """
    from ctypes import wintypes

    class ProcessEntry(ctypes.Structure):
        _fields_ = [
            ("size", wintypes.DWORD), ("usage", wintypes.DWORD), ("pid", wintypes.DWORD),
            ("heap", ctypes.c_size_t), ("module", wintypes.DWORD), ("threads", wintypes.DWORD),
            ("parent", wintypes.DWORD), ("priority", wintypes.LONG), ("flags", wintypes.DWORD),
            ("name", wintypes.WCHAR * 260),
        ]

    kernel = ctypes.WinDLL("kernel32", use_last_error=True)
    kernel.CreateToolhelp32Snapshot.argtypes = [wintypes.DWORD, wintypes.DWORD]
    kernel.CreateToolhelp32Snapshot.restype = wintypes.HANDLE
    kernel.Process32FirstW.argtypes = [wintypes.HANDLE, ctypes.POINTER(ProcessEntry)]
    kernel.Process32FirstW.restype = wintypes.BOOL
    kernel.Process32NextW.argtypes = kernel.Process32FirstW.argtypes
    kernel.Process32NextW.restype = wintypes.BOOL
    kernel.OpenProcess.argtypes = [wintypes.DWORD, wintypes.BOOL, wintypes.DWORD]
    kernel.OpenProcess.restype = wintypes.HANDLE
    kernel.GetProcessTimes.argtypes = [wintypes.HANDLE, *[ctypes.POINTER(wintypes.FILETIME)] * 4]
    kernel.GetProcessTimes.restype = wintypes.BOOL
    kernel.QueryFullProcessImageNameW.argtypes = [
        wintypes.HANDLE, wintypes.DWORD, wintypes.LPWSTR, ctypes.POINTER(wintypes.DWORD)
    ]
    kernel.QueryFullProcessImageNameW.restype = wintypes.BOOL
    kernel.CloseHandle.argtypes = [wintypes.HANDLE]
    kernel.CloseHandle.restype = wintypes.BOOL
    parents: dict[int, int] = {}
    snapshot = kernel.CreateToolhelp32Snapshot(2, 0)  # TH32CS_SNAPPROCESS
    if snapshot not in (None, ctypes.c_void_p(-1).value):
        try:
            row = ProcessEntry()
            row.size = ctypes.sizeof(row)
            valid = kernel.Process32FirstW(snapshot, ctypes.byref(row))
            while valid and len(parents) < 16384:
                parents[int(row.pid)] = int(row.parent)
                valid = kernel.Process32NextW(snapshot, ctypes.byref(row))
        finally:
            kernel.CloseHandle(snapshot)

    def details(pid: int) -> dict[str, Any]:
        handle = kernel.OpenProcess(0x1000, False, pid)  # QUERY_LIMITED_INFORMATION only
        if not handle:
            return {}
        try:
            times = [wintypes.FILETIME() for _ in range(4)]
            if not kernel.GetProcessTimes(handle, *(ctypes.byref(value) for value in times)):
                return {}
            path = ctypes.create_unicode_buffer(32768)
            length = wintypes.DWORD(len(path))
            if not kernel.QueryFullProcessImageNameW(handle, 0, path, ctypes.byref(length)):
                return {}
            if length.value >= len(path):
                return {}
            return {
                "pid": pid, "name": PureWindowsPath(path.value).name, "image": path.value,
                "started_ticks": (times[0].dwHighDateTime << 32) | times[0].dwLowDateTime,
            }
        finally:
            kernel.CloseHandle(handle)

    result: list[dict[str, Any]] = []
    for user in users[:8]:
        current = details(user["pid"])
        if current and current["started_ticks"] != user["started_ticks"]:
            continue  # PID was reused since the resource query; do not misattribute it.
        entry = {**user, **current, "parents": []}
        seen = {user["pid"]}
        for _ in range(4):
            parent_pid = parents.get(current.get("pid", 0), 0)
            if not parent_pid or parent_pid in seen:
                break
            seen.add(parent_pid)
            parent = details(parent_pid)
            if not parent or parent["started_ticks"] > current["started_ticks"]:
                break  # Exited/inaccessible/reused parent: ancestry is unknown.
            if parent["name"].casefold() in {
                "explorer.exe", "wininit.exe", "winlogon.exe", "services.exe", "svchost.exe",
            }:
                break  # Desktop/service infrastructure is not useful app-close advice.
            entry["parents"].append(parent)
            current = parent
        result.append(entry)
    return result


def failed_file_blocker_diagnostic(result: CommandResult) -> dict[str, Any]:
    """Best-effort post-failure advice with a one-second caller budget.

    This is not part of scanning. One in-flight worker per process prevents a
    slow OS query from accumulating workers; its native session still closes
    in finally when the query returns. Failure evidence never changes outcomes.
    """
    if os.name != "nt" or result.timed_out:
        return {}
    path = failed_file_access_path(result.output)
    if not path:
        return {}
    if not _FILE_BLOCKER_PROBE_SLOT.acquire(blocking=False):
        return {"path": path, "state": "busy"}
    report: dict[str, Any] = {"path": path, "state": "inconclusive"}

    def probe() -> None:
        started = time.perf_counter()
        try:
            target = Path(path)
            # Reparse parents can lead to remote storage, even on a drive-letter
            # path. Never traverse one for this optional local-file diagnosis.
            if any(_portable_path_is_reparse_point(p) for p in (target, *target.parents)):
                report["state"] = "unsupported-path"
                return
            if not target.is_file():
                report["state"] = "not-a-file"
                return
            users = _windows_file_users(path)
            report["users"] = _windows_blocker_process_context(users) if users else []
            report["state"] = "file-users-found" if report["users"] else "no-users-found"
        except (OSError, ValueError, AttributeError) as exc:
            report["error"] = f"{type(exc).__name__}: {exc}"
        finally:
            report["duration_seconds"] = round(time.perf_counter() - started, 6)
            _FILE_BLOCKER_PROBE_SLOT.release()

    worker = threading.Thread(target=probe, name="wdp-file-blocker", daemon=True)
    try:
        worker.start()
    except RuntimeError:
        _FILE_BLOCKER_PROBE_SLOT.release()
        return {"path": path, "state": "unavailable"}
    worker.join(timeout=1.0)
    if worker.is_alive():
        return {"path": path, "state": "timed-out"}
    return report


def file_blocker_guidance(report: Mapping[str, Any]) -> str:
    """Keep the observed file user separate from its optional launch context."""
    if report.get("state") != "file-users-found":
        return ""
    lines = [f'Windows reports processes using the failed file "{report["path"]}":']
    for user in report.get("users", []):
        lines.append(f"  {user['name']} (PID {user['pid']})")
        if user.get("parents"):
            lines.append("    Started through: " + " → ".join(
                f"{parent['name']} (PID {parent['pid']})" for parent in user["parents"]
            ))
            # Full image paths help identify background extension/IDE helpers
            # whose executable name alone does not identify the owning app.
            for parent in user["parents"]:
                lines.append(f'    Launcher image: "{parent["image"]}"')
    lines.append(
        "These are likely blockers, not proof that file permissions are correct. "
        "Save work and close the relevant app/task normally, then retry. For a "
        "system process or service, review its role first. WinDevPilot does not "
        "close processes or change permissions."
    )
    return "\n".join(lines)


def winget_installer_failure_hint(
    result: CommandResult,
    related_logs: Sequence[dict[str, Any]],
    item: UpdateItem | None = None,
) -> str:
    if winget_existing_install_permission_failure_path(result):
        return (
            "Failed • existing WinGet package permissions block replacement; "
            "repair only this package folder, then retry"
        )
    content = "\n".join(
        [result.output, *(str(log.get("output", "")) for log in related_logs)]
    ).casefold()
    scope_mismatch = _winget_scope_mismatch_from_text(content)
    if scope_mismatch is not None:
        installer_scope, installed_scope = scope_mismatch
        return (
            f"Not applicable • {installer_scope} installer cannot service the "
            f"installed {installed_scope} scope"
        )
    if (
        item is not None and item.provider == "winget"
        and normalized_exit_code(result.returncode) == 0x8A150010
        and item.installed_technology.casefold() == "exe"
        and item.available_technology.casefold().strip() in {"wix", "msi"}
    ):
        return "Not applicable • possible EXE-to-MSI transition; review the vendor's migration instructions"
    if (
        "the following process(es) use" in content
        and "please terminate those processes and retry" in content
    ):
        return "Failed • close the listed process(es) using this app, then retry"
    if "another installation is already in progress" in content:
        return "Failed • another installer is running; let it finish, then retry"
    child_exit = WINGET_CHILD_INSTALLER_EXIT_RE.search(clean_output(result.output))
    if child_exit:
        child_code = int(child_exit.group("code")) & 0xFFFFFFFF
        if child_code == 0xC0000005:
            return (
                "Failed • the vendor installer crashed with 0xC0000005 "
                "(access violation); close the app and retry, then use its official "
                "installer if the crash repeats"
            )
        if child_code == 0xC000041D:
            return (
                "Failed • the vendor installer crashed with 0xC000041D "
                "(fatal Windows callback exception); close the app and its background "
                "services, then retry or use the vendor's installer if it repeats"
            )
    return ""


def winget_not_applicable_explanation(item: UpdateItem, entry: Mapping[str, Any]) -> str:
    """Explain an exact rejected upgrade using its captured metadata, without probing."""
    code = entry.get("returncode")
    if item.provider != "winget" or entry.get("success") or not isinstance(code, int):
        return ""
    code = normalized_exit_code(code)
    if code == 0x8A15002B:
        detail = (
            "Open Edge > Help and feedback > About Microsoft Edge "
            "(edge://settings/help) to use Edge's own updater; restart Edge if prompted. "
            if item.package_id.casefold() == "microsoft.edge" else
            "Use the application's own updater or review the vendor's migration instructions. "
        )
        return (
            f"{item.name}: WinGet rejected {item.current} → {item.available} with "
            "0x8A15002B: the offered installer technology differs from the installed version. "
            + (f"Installed registration: {item.installed_technology.upper()}. "
               if item.installed_technology else "")
            + (f"Offered installer: {item.available_technology}. "
               if item.available_technology else "The offered installer type was not captured. ")
            + detail
            + "WinDevPilot does not automatically uninstall/reinstall the application. "
            "Repeating the same WinGet attempt will not resolve this mismatch; "
            "run Scan after updating to refresh the installed version."
        )
    if code != 0x8A150010:
        return ""
    installed = item.installed_technology.strip()
    offered = item.available_technology.strip()
    evidence = (
        f" Installed {item.current}: {installed.upper()} registration; "
        f"offered {item.available}: {'WiX/MSI' if offered.casefold() == 'wix' else offered.upper()} installer."
        if installed and offered else ""
    )
    possible_transition = (
        installed.casefold() == "exe" and offered.casefold() in {"wix", "msi"}
    )
    return (
        f"{item.name}: WinGet rejected the requested upgrade with 0x8A150010 "
        f"(no applicable installer).{evidence} "
        + (
            "The EXE-to-MSI change may require a vendor-supported migration; "
            "this return code alone does not prove that is the cause. "
            if possible_transition else
            "The return code alone does not identify whether scope, architecture, "
            "Windows requirements or installer compatibility caused the rejection. "
        )
        + "WinDevPilot submitted the upgrade; it did not perform a replacement install. "
        "Repeating the same command is unlikely to help without a relevant change. "
        "Review the vendor's upgrade/migration instructions and WinGet's diagnostic log. "
        "If a manual migration is required, preserve custom components and PATH choices; "
        "WinDevPilot does not automatically uninstall/reinstall the package. "
        "After completing the vendor-supported update, run Scan to verify the installed version."
    )


def command_for_windows(parts: Sequence[str]) -> list[str]:
    """Resolve an executable and safely accommodate Windows script shims."""
    if not parts:
        raise ValueError("empty command")
    executable = shutil.which(parts[0])
    if executable is None and os.name == "nt" and parts[0].casefold() == "winget":
        # An over-the-shoulder UAC elevation runs under the administrator's
        # identity. That account may not have a per-user App Execution Alias,
        # even though the machine-wide Desktop App Installer contains WinGet.
        windows_apps = Path(os.environ.get("PROGRAMFILES", r"C:\Program Files")) / "WindowsApps"

        def package_version_key(candidate: Path) -> tuple[int, ...]:
            segments = candidate.parent.name.split("_")
            version_text = segments[1] if len(segments) > 1 else ""
            return tuple(int(part) if part.isdigit() else 0 for part in version_text.split("."))

        candidates = sorted(
            windows_apps.glob("Microsoft.DesktopAppInstaller_*__8wekyb3d8bbwe/winget.exe"),
            key=package_version_key,
            reverse=True,
        )
        executable = str(candidates[0]) if candidates else None
    executable = executable or parts[0]
    resolved = [executable, *parts[1:]]
    suffix = Path(executable).suffix.casefold()
    if os.name == "nt" and suffix in {".cmd", ".bat"}:
        comspec = os.environ.get("COMSPEC", r"C:\Windows\System32\cmd.exe")
        return [comspec, "/d", "/c", *resolved]
    if os.name == "nt" and suffix == ".ps1":
        shell = (
            shutil.which("pwsh")
            or shutil.which("powershell")
            or r"C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe"
        )
        return [
            shell,
            "-NoLogo",
            "-NoProfile",
            "-NonInteractive",
            "-ExecutionPolicy",
            "Bypass",
            "-File",
            executable,
            *parts[1:],
        ]
    return resolved


def _kill_process_tree(pid: int | None) -> None:
    if os.name != "nt" or not pid:
        return
    with contextlib.suppress(OSError, subprocess.TimeoutExpired):
        subprocess.run(
            ["taskkill", "/T", "/F", "/PID", str(pid)],
            stdin=subprocess.DEVNULL,
            stdout=subprocess.DEVNULL,
            stderr=subprocess.DEVNULL,
            creationflags=CREATE_NO_WINDOW,
            timeout=15,
            check=False,
        )


# ==================== Commands, parsing, and untrusted-data validation ====================

@dataclasses.dataclass(slots=True)
class CommandResult:
    returncode: int
    output: str
    command: list[str]
    exception: str = ""
    requested_command: list[str] = dataclasses.field(default_factory=list)
    started_at: str = ""
    finished_at: str = ""
    duration_seconds: float = 0.0
    process_id: int | None = None
    timed_out: bool = False
    timeout_seconds: int | None = None
    attempts: tuple[dict[str, Any], ...] = ()
    process_returncode: int | None = None
    capture_bytes: int | None = None
    capture_limit_bytes: int | None = None
    capture_complete: bool = True
    capture_truncated: bool = False
    capture_excerpt: str = ""


class BoundedCommandOutput:
    """Retain exact small transcripts or bounded head/tail evidence, without disk I/O."""

    def __init__(self, limit: int) -> None:
        if isinstance(limit, bool) or not isinstance(limit, int) or limit < 2:
            raise ValueError("command output limit must be at least two bytes")
        self.limit = limit
        self.head_limit = limit // 2
        self.tail_limit = limit - self.head_limit
        self.head = bytearray()
        self.tail = bytearray()
        self.tail_position = 0
        self.byte_count = 0

    def append(self, chunk: bytes) -> None:
        self.byte_count += len(chunk)
        head_bytes = min(len(chunk), self.head_limit - len(self.head))
        if head_bytes:
            self.head.extend(chunk[:head_bytes])
        remaining = chunk[head_bytes:]
        if len(remaining) >= self.tail_limit:
            self.tail[:] = remaining[-self.tail_limit:]
            self.tail_position = 0
            return
        grow = min(len(remaining), self.tail_limit - len(self.tail))
        self.tail.extend(remaining[:grow])
        remaining = remaining[grow:]
        if not remaining:
            return
        # A circular byte buffer also bounds allocation overhead when a child
        # emits many tiny writes; a deque of individual reads would not.
        first = min(len(remaining), self.tail_limit - self.tail_position)
        self.tail[self.tail_position:self.tail_position + first] = remaining[:first]
        self.tail[:len(remaining) - first] = remaining[first:]
        self.tail_position = (self.tail_position + len(remaining)) % self.tail_limit

    def tail_content(self) -> bytes:
        if not self.tail_position:
            return bytes(self.tail)
        return bytes(self.tail[self.tail_position:] + self.tail[:self.tail_position])

    @property
    def truncated(self) -> bool:
        return self.byte_count > self.limit

    def text(self) -> str:
        head, tail = bytes(self.head), self.tail_content()
        if not self.truncated:
            return clean_output(decode_console_output(head + tail))
        # Decode the two byte ranges separately: neither the omission marker nor
        # a partial multibyte character should change the other range's encoding.
        # Drop partial boundary lines before redaction. Otherwise a tail cut
        # midway through a credential can lose its identifying label and expose
        # a fragment which the ordinary line-oriented redactor cannot recognize.
        head_text = clean_output(decode_console_output(head)).rpartition("\n")[0]
        tail_text = clean_output(decode_console_output(tail)).partition("\n")[2]
        return (
            head_text
            + f"\n\n[WinDevPilot capture exceeded {self.limit} bytes; "
            "middle and partial boundary lines omitted]\n\n"
            + tail_text
        )


@dataclasses.dataclass(frozen=True, slots=True)
class _RecentWingetInventoryEntry:
    captured_at: float
    rows: tuple[tuple[tuple[str, str], ...], ...]


class _RecentWingetInventoryCache:
    """Short-lived, process-local evidence cache for scoped ``winget list`` output.

    Refresh tokens prevent a scan that began before an update/uninstall from
    repopulating the cache after that package operation invalidates it.
    """

    def __init__(self, ttl_seconds: float) -> None:
        self.ttl_seconds = ttl_seconds
        self._lock = threading.Lock()
        self._generation = 0
        self._scope_revisions: dict[str, int] = {}
        self._entries: dict[str, _RecentWingetInventoryEntry] = {}

    def get(self, scope: str) -> list[dict[str, str]] | None:
        now = time.monotonic()
        with self._lock:
            entry = self._entries.get(scope)
            if entry is None:
                return None
            if now - entry.captured_at > self.ttl_seconds:
                self._entries.pop(scope, None)
                return None
            return [dict(row) for row in entry.rows]

    def begin_refresh(self, scope: str) -> tuple[int, int]:
        with self._lock:
            revision = self._scope_revisions.get(scope, 0) + 1
            self._scope_revisions[scope] = revision
            self._entries.pop(scope, None)
            return self._generation, revision

    def store(
        self,
        scope: str,
        token: tuple[int, int],
        rows: Sequence[Mapping[str, str]],
    ) -> bool:
        frozen_rows = tuple(tuple((str(key), str(value)) for key, value in row.items()) for row in rows)
        with self._lock:
            expected = (self._generation, self._scope_revisions.get(scope, 0))
            if token != expected:
                return False
            self._entries[scope] = _RecentWingetInventoryEntry(time.monotonic(), frozen_rows)
            return True

    def invalidate(self) -> None:
        with self._lock:
            self._generation += 1
            self._entries.clear()


_RECENT_WINGET_INVENTORY = _RecentWingetInventoryCache(
    WINGET_RECENT_INVENTORY_TTL_SECONDS
)


def immediate_command_error(
    error: str, *, requested_command: Sequence[str] = (), returncode: int = 2
) -> CommandResult:
    timestamp = utc_now_iso()
    return CommandResult(
        returncode=returncode,
        output="",
        command=[],
        exception=error,
        requested_command=list(requested_command),
        started_at=timestamp,
        finished_at=timestamp,
    )


_COMMAND_LAUNCH_CONTEXT = threading.local()


@contextlib.contextmanager
def background_command_process_priority() -> Iterator[None]:
    """Launch commands below normal priority within one scan-provider thread."""

    previous = bool(getattr(_COMMAND_LAUNCH_CONTEXT, "below_normal", False))
    _COMMAND_LAUNCH_CONTEXT.below_normal = True
    try:
        yield
    finally:
        _COMMAND_LAUNCH_CONTEXT.below_normal = previous


def run_capture(
    parts: Sequence[str],
    *,
    timeout: int = 900,
    max_output_bytes: int | None = None,
) -> CommandResult:
    """Drain bounded output while timing process execution independently of EOF.

    Overflow never interrupts a running installer. Partial transcripts are kept
    only as diagnostic excerpts, not as parser input; native exit status remains
    separate from the synthetic timeout/capture-error status used by callers.
    """

    capture = BoundedCommandOutput(
        MAX_COMMAND_OUTPUT_BYTES if max_output_bytes is None else max_output_bytes
    )
    requested_command = list(parts)
    started_at = utc_now_iso()
    started_clock = time.perf_counter()
    command = requested_command
    env = os.environ.copy()
    env.setdefault("NO_COLOR", "1")
    env.setdefault("TERM", "dumb")
    env.setdefault("DOTNET_NOLOGO", "true")
    env.setdefault("DOTNET_CLI_TELEMETRY_OPTOUT", "1")
    process: subprocess.Popen[bytes] | None = None
    drained = threading.Event()
    stop_reader = threading.Event()
    read_complete = False
    read_error = ""
    timed_out = False
    error = ""
    try:
        command = command_for_windows(parts)
        process = subprocess.Popen(
            command,
            stdin=subprocess.DEVNULL,
            stdout=subprocess.PIPE,
            stderr=subprocess.STDOUT,
            env=env,
            creationflags=(
                CREATE_NO_WINDOW
                | (
                    BELOW_NORMAL_PRIORITY_CLASS
                    if getattr(_COMMAND_LAUNCH_CONTEXT, "below_normal", False)
                    else 0
                )
            ),
        )
        deadline = time.monotonic() + timeout
        stream = process.stdout
        assert stream is not None

        def drain() -> None:
            nonlocal read_complete, read_error
            try:
                with stream:
                    descriptor = stream.fileno()
                    # Supported for Windows pipes since Python 3.12. This reader
                    # owns the stream and can finish even if descendants retain
                    # a write handle; no blocked read thread is left behind.
                    os.set_blocking(descriptor, False)
                    while not stop_reader.is_set():
                        try:
                            chunk = os.read(descriptor, COMMAND_OUTPUT_CHUNK_BYTES)
                        except BlockingIOError:
                            stop_reader.wait(0.01)
                            continue
                        if not chunk:
                            read_complete = True
                            break
                        capture.append(chunk)
            except Exception as exc:
                read_error = f"output read failed: {type(exc).__name__}: {exc}"
            finally:
                drained.set()

        threading.Thread(target=drain, name="wdp-command-output", daemon=True).start()
        process.wait(timeout=max(0.0, deadline - time.monotonic()))
        if not drained.wait(2.0):
            read_error = "pipe-open-after-process-exit"
            stop_reader.set()
            drained.wait(1.0)
    except subprocess.TimeoutExpired:
        timed_out = True
        error = f"timed out after {timeout}s"
        if process is not None and process.poll() is None:
            _kill_process_tree(process.pid)
            try:
                process.wait(timeout=10)
            except subprocess.TimeoutExpired:
                with contextlib.suppress(OSError):
                    process.kill()
                with contextlib.suppress(OSError, subprocess.TimeoutExpired):
                    process.wait(timeout=2)
            # A descendant may still own the pipe. Do not close a buffered
            # stream from another thread or enter an unbounded final read.
            drained.wait(2)
        stop_reader.set()
        drained.wait(1.0)
    except (OSError, ValueError) as exc:
        return CommandResult(
            returncode=127,
            output="",
            command=command,
            exception=str(exc),
            requested_command=requested_command,
            started_at=started_at,
            finished_at=utc_now_iso(),
            duration_seconds=round(time.perf_counter() - started_clock, 3),
            process_id=process.pid if process is not None else None,
            timeout_seconds=timeout,
        )
    finished_read = drained.is_set()
    complete = finished_read and read_complete
    truncated = finished_read and capture.truncated
    transcript = capture.text() if finished_read else ""
    capture_error = ""
    if not complete:
        capture_error = read_error or "output pipe did not reach EOF during bounded cleanup"
    elif truncated:
        capture_error = (
            f"output exceeded the {capture.limit}-byte capture limit; verify before retrying"
        )
    error = "; ".join(part for part in (error, capture_error) if part)
    native_code = process.returncode if process is not None else None
    return CommandResult(
        returncode=124 if timed_out else 125 if capture_error else int(native_code),
        output="" if capture_error else transcript,
        command=command,
        exception=error,
        requested_command=requested_command,
        started_at=started_at,
        finished_at=utc_now_iso(),
        duration_seconds=round(time.perf_counter() - started_clock, 3),
        process_id=process.pid if process is not None else None,
        timed_out=timed_out,
        timeout_seconds=timeout,
        process_returncode=native_code,
        capture_bytes=capture.byte_count if finished_read else None,
        capture_limit_bytes=capture.limit,
        capture_complete=complete,
        capture_truncated=truncated,
        capture_excerpt=transcript if capture_error else "",
    )


def _parse_fixed_table_lines(
    lines: Sequence[str], headers: Sequence[str]
) -> list[dict[str, str]]:
    """Parse already-cleaned lines from the fixed-width tables emitted by WinGet.

    Column positions come from the header rather than hard-coded widths. This
    survives long package names touching the next column and future width
    adjustments better than whitespace splitting.
    """
    header_index = -1
    starts: list[int] = []
    for index, line in enumerate(lines):
        positions: list[int] = []
        cursor = 0
        for header in headers:
            position = line.find(header, cursor)
            if position < 0:
                positions = []
                break
            positions.append(position)
            cursor = position + len(header)
        if positions:
            header_index = index
            starts = positions
            break
    if header_index < 0:
        # WinGet localizes its visible headings but retains fixed-width columns.
        # Discover those columns from the header immediately above the divider,
        # then map them by the command's stable column order supplied by callers.
        for index, line in enumerate(lines[:-1]):
            divider_line = lines[index + 1]
            following = divider_line.strip()
            if len(following) < 8 or set(following) - {"-", " "}:
                continue
            divider_spans = list(re.finditer(r"-+", divider_line))
            if len(divider_spans) == len(headers):
                starts = [match.start() for match in divider_spans]
            else:
                # Current WinGet normally emits one continuous divider. In that
                # form the localized heading groups, separated by alignment
                # whitespace, remain the only language-neutral column markers.
                header_spans = list(re.finditer(r"\S(?:.*?\S)?(?=\s{2,}|$)", line))
                if len(header_spans) != len(headers):
                    continue
                starts = [match.start() for match in header_spans]
            header_index = index
            break
    if header_index < 0:
        return []

    rows: list[dict[str, str]] = []
    started = False
    for raw_line in lines[header_index + 1 :]:
        if not raw_line.strip():
            if started:
                break
            continue
        stripped = raw_line.strip()
        if set(stripped) <= {"-", " "}:
            continue
        if re.fullmatch(
            r"\d+\s+(?:"
            r"upgrades?\s+available"
            r"|package(?:\(s\)|s)?\s+installed"
            r"|package(?:\(s\)|s)?\s+are\s+pinned\s+and\s+need\s+to\s+be\s+"
            r"explicitly\s+upgraded"
            r"|package(?:\(s\)|s)?\s+have\s+version\s+numbers\s+that\s+cannot\s+"
            r"be\s+determined(?:\.\s+use\s+--include-unknown\s+to\s+see\s+all\s+results)?"
            r")\.?",
            stripped,
            re.IGNORECASE,
        ):
            break
        if stripped.startswith("No installed package"):
            break
        values: list[str] = []
        for column, start in enumerate(starts):
            end = starts[column + 1] if column + 1 < len(starts) else None
            values.append(raw_line[start:end].strip())
        if len(values) != len(headers) or not values[1]:
            if started:
                break
            continue
        started = True
        rows.append(dict(zip(headers, values, strict=True)))
    return rows


def parse_fixed_table(text: str, headers: Sequence[str]) -> list[dict[str, str]]:
    """Clean and parse one fixed-width WinGet table."""

    return _parse_fixed_table_lines(clean_output(text).splitlines(), headers)


def parse_winget_table_consensus(
    text: str,
    headers: Sequence[str],
    *,
    require_version: bool = True,
    require_available: bool = False,
) -> list[dict[str, str]]:
    """Accept WinGet table rows only when geometry and token views agree."""

    clean_lines = clean_output(text).splitlines()
    rows = _parse_fixed_table_lines(clean_lines, headers)
    if not rows:
        return []
    raw_token_rows = [line.split() for line in clean_lines if line.strip()]
    search_start = 0
    for row in rows:
        package_id = row.get("Id", "").strip()
        current = row.get("Version", "").strip()
        available = row.get("Available", "").strip()
        source = row.get("Source", "").strip()
        if not valid_inventory_id(package_id) or (require_version and not current):
            raise ValueError("WinGet table contained an invalid package identity or version")
        if require_available and not available:
            raise ValueError("WinGet update table omitted an available version")
        if source and not valid_provider_source(source):
            raise ValueError("WinGet table contained an invalid package source")
        expected_tokens: list[str] = []
        for header in headers:
            expected_tokens.extend(row.get(header, "").split())
        for index in range(search_start, len(raw_token_rows)):
            if raw_token_rows[index] == expected_tokens:
                search_start = index + 1
                break
        else:
            raise ValueError(
                "WinGet table geometry disagreed with its whitespace-token representation"
            )
    return rows


def _winget_json_array(payload: Any) -> list[Any]:
    """Extract only a small set of explicit package-array shapes."""

    if isinstance(payload, list):
        return payload
    if not isinstance(payload, dict):
        raise ValueError("WinGet structured output root is not an object or array")
    folded = {str(key).casefold(): value for key, value in payload.items()}
    for key in ("packages", "items"):
        if isinstance(folded.get(key), list):
            return folded[key]
    data = folded.get("data")
    if isinstance(data, list):
        return data
    if isinstance(data, dict):
        nested = {str(key).casefold(): value for key, value in data.items()}
        for key in ("packages", "items"):
            if isinstance(nested.get(key), list):
                return nested[key]
    raise ValueError("WinGet structured output has no recognized package array")


def parse_winget_structured_rows(text: str, *, updates: bool) -> list[dict[str, str]]:
    """Validate a conservative family of future WinGet JSON package schemas."""

    def reject_duplicate_pairs(pairs: Sequence[tuple[str, Any]]) -> dict[str, Any]:
        output: dict[str, Any] = {}
        for key, value in pairs:
            folded = str(key).casefold()
            if folded in output:
                raise ValueError(f"duplicate WinGet JSON key: {key}")
            output[folded] = value
        return output

    payload = json.loads(
        clean_output(text),
        object_pairs_hook=reject_duplicate_pairs,
        parse_constant=lambda value: (_ for _ in ()).throw(
            ValueError(f"unsupported WinGet JSON constant: {value}")
        ),
    )
    entries = _winget_json_array(payload)
    rows: list[dict[str, str]] = []
    aliases = {
        "Name": ("name", "packagename"),
        "Id": ("id", "packageid", "packageidentifier"),
        "Version": ("version", "installedversion"),
        "Available": ("available", "availableversion"),
        "Source": ("source", "sourcename"),
    }
    for raw_entry in entries:
        if not isinstance(raw_entry, dict):
            raise ValueError("WinGet structured package entry is not an object")
        entry = {str(key).casefold(): value for key, value in raw_entry.items()}
        row: dict[str, str] = {}
        for output_key, possible_keys in aliases.items():
            value = next((entry[key] for key in possible_keys if key in entry), "")
            if value is None:
                value = ""
            if not isinstance(value, (str, int, float)) or isinstance(value, bool):
                raise ValueError(f"WinGet structured {output_key} field is not scalar")
            row[output_key] = str(value).strip()
        if not row["Name"]:
            row["Name"] = row["Id"]
        if not valid_inventory_id(row["Id"]) or not row["Version"]:
            raise ValueError("WinGet structured package identity or version is invalid")
        if updates and not row["Available"]:
            raise ValueError("WinGet structured update omitted its available version")
        if row["Source"] and not valid_provider_source(row["Source"]):
            raise ValueError("WinGet structured package source is invalid")
        rows.append(row)
    return rows


@functools.lru_cache(maxsize=4)
def winget_structured_output_arguments(command: str) -> tuple[str, ...]:
    """Discover, rather than assume, a future WinGet JSON-output switch."""

    result = run_capture(["winget", command, "--help"], timeout=30)
    if result.returncode != 0:
        return ()
    lines = clean_output(result.output).splitlines()
    for index, line in enumerate(lines):
        window = " ".join(lines[index : index + 2]).casefold()
        if "json" not in window:
            continue
        if re.search(r"(?:^|\s)--output(?:\s|,|=|$)", line, re.IGNORECASE):
            return ("--output", "json")
        if re.search(r"(?:^|\s)--format(?:\s|,|=|$)", line, re.IGNORECASE):
            return ("--format", "json")
    return ()


def winget_output_proves_empty_upgrade_inventory(text: str) -> bool:
    """Recognize WinGet's exact native empty result for an unfiltered upgrade list."""

    lines = [
        line.strip().casefold()
        for line in clean_output(text).splitlines()
        if line.strip()
    ]
    return lines == ["no installed package found matching input criteria."]


def output_looks_like_package_table(text: str) -> bool:
    cleaned_text = clean_output(text)
    cleaned = cleaned_text.casefold()
    has_fixed_width_divider = any(
        len(stripped) >= 8 and not (set(stripped) - {"-", " "})
        for line in cleaned_text.splitlines()
        if (stripped := line.strip())
    )
    return bool(cleaned.strip()) and (
        has_fixed_width_divider
        or
        (" name" in f" {cleaned}" and " id" in f" {cleaned}" and "version" in cleaned)
        or "upgrades available" in cleaned
        or "packages installed" in cleaned
    )


SUGGESTION_TIERS = frozenset({"essential", "recommended", "optional"})
SUGGESTION_PROFILES = frozenset(
    {"AI", "CLI", "Containers", "Editors", "Game development", "Graphics", "Native", "Web"}
)
SUGGESTION_SCOPE_POLICIES = frozenset({"auto", "user", "machine"})


@dataclasses.dataclass(frozen=True, slots=True)
class PackageSuggestion:
    winget_id: str
    title: str
    summary: str
    category: str
    homepage: str
    provider_key: str = "winget"
    tier: str = "optional"
    profiles: tuple[str, ...] = ()
    alternatives_group: str = ""
    account_required: bool = False
    service_cost: str = "none"
    large_download: bool = False
    system_changes: tuple[str, ...] = ()
    prerequisites: tuple[str, ...] = ()
    scope_policy: str = "auto"
    presence_commands: tuple[str, ...] = ()

    def to_dict(self) -> dict[str, Any]:
        return {
            "winget_id": self.winget_id,
            "title": self.title,
            "summary": self.summary,
            "category": self.category,
            "homepage": self.homepage,
            "provider_key": self.provider_key,
            "tier": self.tier,
            "profiles": list(self.profiles),
            "alternatives_group": self.alternatives_group,
            "account_required": self.account_required,
            "service_cost": self.service_cost,
            "large_download": self.large_download,
            "system_changes": list(self.system_changes),
            "prerequisites": list(self.prerequisites),
            "scope_policy": self.scope_policy,
            "presence_commands": list(self.presence_commands),
        }


PACKAGE_SUGGESTIONS: tuple[PackageSuggestion, ...] = (
    PackageSuggestion(
        "Git.Git",
        "Git for Windows",
        "Essential source-control CLI and shell integration for Windows development.",
        "CLI essentials",
        "https://gitforwindows.org/",
    ),
    PackageSuggestion(
        "Microsoft.PowerShell",
        "PowerShell 7",
        "Modern cross-platform automation shell from Microsoft.",
        "Core shell",
        "https://learn.microsoft.com/powershell/",
    ),
    PackageSuggestion(
        "Microsoft.WindowsTerminal",
        "Windows Terminal",
        "Modern tabbed terminal host for Windows command-line work.",
        "Core shell",
        "https://learn.microsoft.com/windows/terminal/",
    ),
    PackageSuggestion(
        "Microsoft.PowerToys",
        "PowerToys",
        "Microsoft power-user utilities, including File Explorer add-ons.",
        "Windows productivity",
        "https://learn.microsoft.com/windows/powertoys/",
    ),
    PackageSuggestion(
        "Microsoft.Sysinternals.Suite",
        "Microsoft Sysinternals Suite",
        "Advanced Windows diagnostics, troubleshooting, process, disk, and network utilities.",
        "Windows diagnostics",
        "https://learn.microsoft.com/sysinternals/downloads/sysinternals-suite",
        profiles=("CLI", "Native"),
    ),
    PackageSuggestion(
        "GitHub.cli",
        "GitHub CLI",
        "GitHub issues, pull requests, releases, and API workflows from the terminal.",
        "CLI essentials",
        "https://cli.github.com/",
    ),
    PackageSuggestion(
        "GitHub.GitLFS",
        "Git Large File Storage",
        "Git extension for versioning large binary assets without bloating ordinary repositories.",
        "CLI essentials",
        "https://git-lfs.com/",
        profiles=("CLI",),
        presence_commands=("git-lfs",),
    ),
    PackageSuggestion(
        "astral-sh.uv",
        "uv",
        "Fast Python package, tool, and environment manager.",
        "CLI essentials",
        "https://docs.astral.sh/uv/",
    ),
    PackageSuggestion(
        "gerardog.gsudo",
        "gsudo",
        "sudo-like elevation helper for Windows developer terminals.",
        "CLI essentials",
        "https://github.com/gerardog/gsudo",
    ),
    PackageSuggestion(
        "JanDeDobbeleer.OhMyPosh",
        "Oh My Posh",
        "Cross-shell prompt theme engine for PowerShell, Windows Terminal, and other shells.",
        "CLI essentials",
        "https://ohmyposh.dev/",
    ),
    PackageSuggestion(
        "7zip.7zip",
        "7-Zip",
        "Reliable archive inspection and extraction tool.",
        "CLI essentials",
        "https://www.7-zip.org/",
    ),
    PackageSuggestion(
        "BurntSushi.ripgrep.MSVC",
        "ripgrep",
        "Fast recursive code search with ignore-file support.",
        "CLI essentials",
        "https://ripgrep.dev/",
    ),
    PackageSuggestion(
        "sharkdp.fd",
        "fd",
        "Fast, friendly file finder that complements ripgrep.",
        "CLI essentials",
        "https://github.com/sharkdp/fd",
    ),
    PackageSuggestion(
        "jqlang.jq",
        "jq",
        "Command-line JSON processor for API, config, and log workflows.",
        "CLI essentials",
        "https://jqlang.org/",
    ),
    PackageSuggestion(
        "junegunn.fzf",
        "fzf",
        "Fast interactive fuzzy finder for files, command history, and pipelines.",
        "CLI essentials",
        "https://junegunn.github.io/fzf/",
    ),
    PackageSuggestion(
        "sharkdp.bat",
        "bat",
        "Syntax-aware file viewer that complements command-line search tools.",
        "CLI essentials",
        "https://github.com/sharkdp/bat",
    ),
    PackageSuggestion(
        "ajeetdsouza.zoxide",
        "zoxide",
        "Smarter directory navigation that learns frequently used locations.",
        "CLI essentials",
        "https://github.com/ajeetdsouza/zoxide",
    ),
    PackageSuggestion(
        "dandavison.delta",
        "delta",
        "Readable syntax-highlighted diffs for Git and terminal workflows.",
        "CLI essentials",
        "https://dandavison.github.io/delta/",
    ),
    PackageSuggestion(
        "OpenJS.NodeJS.LTS",
        "Node.js LTS",
        "Long-term-support JavaScript runtime used by npm applications and developer tools.",
        "Web and runtimes",
        "https://nodejs.org/",
        presence_commands=("node",),
    ),
    PackageSuggestion(
        "Microsoft.DotNet.SDK.10",
        ".NET 10 SDK",
        "Current .NET compiler, CLI, runtime, and project tooling for application development.",
        "Web and runtimes",
        "https://dotnet.microsoft.com/download/dotnet/10.0",
        profiles=("Native", "Web"),
    ),
    PackageSuggestion(
        "GoLang.Go",
        "Go programming language",
        "Go compiler, standard library, module tooling, formatter, and developer commands.",
        "Web and runtimes",
        "https://go.dev/",
        profiles=("Native", "Web"),
        presence_commands=("go",),
    ),
    PackageSuggestion(
        "Oven-sh.Bun",
        "Bun",
        "Fast JavaScript and TypeScript runtime, package manager, test runner, and bundler.",
        "Web and runtimes",
        "https://bun.sh/",
    ),
    PackageSuggestion(
        "DenoLand.Deno",
        "Deno",
        "Secure-by-default JavaScript and TypeScript runtime with integrated tooling.",
        "Web and runtimes",
        "https://deno.com/",
    ),
    PackageSuggestion(
        "Casey.Just",
        "Just",
        "Simple command runner for repeatable project tasks across development stacks.",
        "CLI essentials",
        "https://just.systems/",
    ),
    PackageSuggestion(
        "MikeFarah.yq",
        "yq",
        "Command-line YAML, JSON, XML, CSV, and properties processor.",
        "CLI essentials",
        "https://mikefarah.gitbook.io/yq/",
    ),
    PackageSuggestion(
        "Kitware.CMake",
        "CMake",
        "Widely used cross-platform build-system generator for native projects.",
        "Native build",
        "https://cmake.org/",
    ),
    PackageSuggestion(
        "Ninja-build.Ninja",
        "Ninja",
        "Small, fast build executor commonly paired with CMake.",
        "Native build",
        "https://ninja-build.org/",
    ),
    PackageSuggestion(
        "Rustlang.Rustup",
        "Rustup",
        "Official Rust toolchain installer and stable, beta, and nightly version manager.",
        "Native build",
        "https://rustup.rs/",
    ),
    PackageSuggestion(
        "Neovim.Neovim",
        "Neovim",
        "Terminal-first extensible editor.",
        "Editors",
        "https://neovim.io/",
    ),
    PackageSuggestion(
        "Microsoft.VisualStudioCode",
        "Visual Studio Code",
        "Common GUI editor with strong extension support for Windows development.",
        "Editors",
        "https://code.visualstudio.com/",
    ),
    PackageSuggestion(
        "Microsoft.VisualStudio.2022.BuildTools",
        "Visual Studio Build Tools 2022",
        "Native Windows build chain for C/C++, Python wheels, and related tooling.",
        "Native build",
        "https://visualstudio.microsoft.com/downloads/",
        tier="recommended",
        profiles=("Native",),
        large_download=True,
        system_changes=("Installs compiler, SDK, and build-system components",),
    ),
    PackageSuggestion(
        "LLVM.LLVM",
        "LLVM",
        "Clang/LLVM compiler toolchain for native development.",
        "Native build",
        "https://llvm.org/",
    ),
    PackageSuggestion(
        "Docker.DockerDesktop",
        "Docker Desktop",
        "Container workflow for local development on Windows.",
        "Containers/devops",
        "https://www.docker.com/products/docker-desktop/",
        profiles=("Containers",),
        service_cost="license depends on organization and use",
        large_download=True,
        system_changes=("Runs background services", "May enable WSL 2 or Hyper-V"),
        prerequisites=("Hardware virtualization",),
    ),
    PackageSuggestion(
        "Microsoft.WSL",
        "Windows Subsystem for Linux",
        "Microsoft's Linux environment foundation for command-line, build, and container workflows.",
        "Containers/devops",
        "https://learn.microsoft.com/windows/wsl/",
        profiles=("CLI", "Containers", "Web"),
        large_download=True,
        system_changes=(
            "Installs or updates Windows Linux-subsystem components",
            "May require a restart",
        ),
    ),
    PackageSuggestion(
        "OpenAI.Codex",
        "OpenAI Codex CLI",
        "Terminal coding agent for repository-scale planning, editing, testing, and review.",
        "AI development",
        "https://github.com/openai/codex",
        tier="recommended",
        profiles=("AI", "CLI"),
        alternatives_group="hosted-coding-agent",
        account_required=True,
        service_cost="plan-dependent",
    ),
    PackageSuggestion(
        "Anthropic.ClaudeCode",
        "Claude Code",
        "Terminal coding agent for working across repositories with Anthropic models.",
        "AI development",
        "https://docs.anthropic.com/en/docs/claude-code/overview",
        profiles=("AI", "CLI"),
        alternatives_group="hosted-coding-agent",
        account_required=True,
        service_cost="subscription or metered service",
    ),
    PackageSuggestion(
        "Ollama.Ollama",
        "Ollama",
        "Local model runtime and API for running open-weight language models on Windows.",
        "AI development",
        "https://ollama.com/",
        tier="recommended",
        profiles=("AI",),
        alternatives_group="local-model-host",
        system_changes=("Runs a local model service", "Model downloads can use many gigabytes"),
    ),
    PackageSuggestion(
        "ElementLabs.LMStudio",
        "LM Studio",
        "Desktop interface and local server for discovering and running language models.",
        "AI development",
        "https://lmstudio.ai/",
        profiles=("AI",),
        alternatives_group="local-model-host",
        large_download=True,
        system_changes=("Model downloads can use many gigabytes",),
    ),
    PackageSuggestion(
        "BaldurKarlsson.RenderDoc",
        "RenderDoc",
        "Frame-capture and graphics debugger for Direct3D, Vulkan, and related GPU workloads.",
        "Native build",
        "https://renderdoc.org/",
        tier="recommended",
        profiles=("Native", "Graphics", "Game development"),
    ),
)


def package_suggestion_catalog_errors(
    suggestions: Sequence[PackageSuggestion] = PACKAGE_SUGGESTIONS,
) -> list[str]:
    """Validate durable catalog structure without touching the network or WinGet."""

    errors: list[str] = []
    normalized_ids: Counter[str] = Counter(item.winget_id.casefold() for item in suggestions)
    for package_id, count in normalized_ids.items():
        if count > 1:
            errors.append(f"duplicate package ID: {package_id} ({count} entries)")
    alternative_counts = Counter(
        item.alternatives_group for item in suggestions if item.alternatives_group
    )
    for suggestion in suggestions:
        prefix = suggestion.winget_id or "<missing ID>"
        if not valid_package_id(suggestion.winget_id):
            errors.append(f"{prefix}: invalid package ID")
        if suggestion.provider_key != WingetProvider.key:
            errors.append(f"{prefix}: unsupported provider {suggestion.provider_key!r}")
        parsed_homepage = urllib.parse.urlparse(suggestion.homepage)
        if parsed_homepage.scheme not in {"http", "https"} or not parsed_homepage.netloc:
            errors.append(f"{prefix}: invalid homepage URL")
        if suggestion.tier not in SUGGESTION_TIERS:
            errors.append(f"{prefix}: unknown tier {suggestion.tier!r}")
        unknown_profiles = sorted(set(suggestion.profiles) - SUGGESTION_PROFILES)
        if unknown_profiles:
            errors.append(f"{prefix}: unknown profiles {', '.join(unknown_profiles)}")
        if suggestion.scope_policy not in SUGGESTION_SCOPE_POLICIES:
            errors.append(f"{prefix}: unknown scope policy {suggestion.scope_policy!r}")
        invalid_presence_commands = [
            command
            for command in suggestion.presence_commands
            if not re.fullmatch(r"[A-Za-z0-9_.+-]+", command)
        ]
        if invalid_presence_commands:
            errors.append(
                f"{prefix}: invalid presence commands {', '.join(invalid_presence_commands)}"
            )
        if suggestion.alternatives_group and alternative_counts[suggestion.alternatives_group] < 2:
            errors.append(
                f"{prefix}: alternatives group {suggestion.alternatives_group!r} has one entry"
            )
    return errors


def validate_package_suggestions_with_winget() -> int:
    """Release-time exact-ID validation; never called during normal GUI startup."""

    errors = package_suggestion_catalog_errors()
    if shutil.which("winget") is None:
        errors.append("winget was not found on PATH")
    else:
        for suggestion in PACKAGE_SUGGESTIONS:
            result = run_capture(
                [
                    "winget",
                    "search",
                    "--id",
                    suggestion.winget_id,
                    "--exact",
                    "--source",
                    "winget",
                    "--accept-source-agreements",
                    "--disable-interactivity",
                ],
                timeout=60,
            )
            if result.returncode != 0 or suggestion.winget_id.casefold() not in result.output.casefold():
                detail = result.exception or result.output.strip() or f"exit {result.returncode}"
                errors.append(f"{suggestion.winget_id}: no exact WinGet match ({detail[-160:]})")
            else:
                print(f"OK  {suggestion.winget_id}")
    if errors:
        for error in errors:
            print(f"ERROR  {error}", file=sys.stderr)
        return 1
    print(f"Validated {len(PACKAGE_SUGGESTIONS)} package suggestions.")
    return 0


def build_missing_package_suggestions(
    installed_ids: set[str],
    available_commands: set[str] | None = None,
) -> list[PackageSuggestion]:
    normalized = {value.casefold() for value in installed_ids}
    commands = {value.casefold() for value in (available_commands or set())}
    return [
        suggestion
        for suggestion in PACKAGE_SUGGESTIONS
        if suggestion.winget_id.casefold() not in normalized
        and not any(command.casefold() in commands for command in suggestion.presence_commands)
    ]


def available_suggestion_presence_commands() -> set[str]:
    """Return curated command probes that are genuinely available to this account."""

    commands = {
        command
        for suggestion in PACKAGE_SUGGESTIONS
        for command in suggestion.presence_commands
    }
    return {command for command in commands if shutil.which(command) is not None}


def suggestion_install_command_parts(suggestion: PackageSuggestion) -> list[str]:
    """Return one exact, unattended install request for a curated suggestion."""

    if suggestion.provider_key != WingetProvider.key:
        raise ValueError(f"unsupported suggestion provider: {suggestion.provider_key!r}")
    if not valid_package_id(suggestion.winget_id):
        raise ValueError(f"unsafe WinGet package id: {suggestion.winget_id!r}")
    return [
        "winget",
        "install",
        "--id",
        suggestion.winget_id,
        "--exact",
        "--source",
        "winget",
        "--silent",
        "--disable-interactivity",
        "--accept-source-agreements",
        "--accept-package-agreements",
        "--authentication-mode",
        "silentPreferred",
        "--verbose-logs",
    ]


def suggestion_install_command(suggestion: PackageSuggestion) -> str:
    return subprocess.list2cmdline(suggestion_install_command_parts(suggestion))


def winget_installed_ids_for_suggestions(
    *, bypass_recent_cache: bool = False
) -> tuple[set[str], list[str]]:
    """Return scoped WinGet IDs through the provider's validated inventory reader."""

    installed_ids: set[str] = set()
    provider = WingetProvider()
    for scope in ("user", "machine"):
        rows = provider._installed_inventory_rows(
            scope,
            allow_recent=not bypass_recent_cache,
        )
        installed_ids.update(
            row["Id"].casefold() for row in rows if row.get("Id") and valid_package_id(row["Id"])
        )
    return installed_ids, list(provider.warnings)


def normalized_manifest_value(value: str) -> str:
    return re.sub(r"\s+", "-", value.strip().casefold())


@dataclasses.dataclass(slots=True, frozen=True)
class WingetManifestMetadata:
    package_id: str
    source: str
    returncode: int
    installer_types: tuple[str, ...] = ()
    scopes: tuple[str, ...] = ()
    upgrade_behaviors: tuple[str, ...] = ()
    raw_fields: dict[str, str] = dataclasses.field(default_factory=dict)
    error: str = ""

    @property
    def installer_type_summary(self) -> str:
        return summarize_manifest_values(self.installer_types)

    @property
    def scope_summary(self) -> str:
        return summarize_manifest_values(self.scopes)

    @property
    def upgrade_behavior_summary(self) -> str:
        return summarize_manifest_values(self.upgrade_behaviors)


@dataclasses.dataclass(slots=True, frozen=True)
class PipSideEffects:
    touched_packages: tuple[str, ...] = ()
    successfully_installed: dict[str, str] = dataclasses.field(default_factory=dict)
    resolver_conflicts: tuple[str, ...] = ()
    scripts_not_on_path: tuple[str, ...] = ()
    generic_error_warnings: tuple[str, ...] = ()

    @property
    def has_warnings(self) -> bool:
        return bool(
            self.resolver_conflicts or self.scripts_not_on_path or self.generic_error_warnings
        )

    def to_dict(self) -> dict[str, Any]:
        return {
            "touched_packages": list(self.touched_packages),
            "successfully_installed": dict(self.successfully_installed),
            "resolver_conflicts": list(self.resolver_conflicts),
            "scripts_not_on_path": list(self.scripts_not_on_path),
            "generic_error_warnings": list(self.generic_error_warnings),
            "has_warnings": self.has_warnings,
        }


def _parse_successfully_installed_token(token: str) -> tuple[str, str] | None:
    if "-" not in token:
        return None
    name, version = token.rsplit("-", 1)
    if not name or not version:
        return None
    return name, version


def parse_pip_install_output(output: str) -> PipSideEffects:
    touched: set[str] = set()
    installed: dict[str, str] = {}
    conflicts: list[str] = []
    path_warnings: list[str] = []
    generic_errors: list[str] = []
    in_conflict_block = False
    for raw_line in clean_output(output).splitlines():
        line = raw_line.strip()
        if not line:
            in_conflict_block = False
            continue
        if line.startswith("Installing collected packages:"):
            packages = line.split(":", 1)[1]
            touched.update(package.strip() for package in packages.split(",") if package.strip())
            continue
        if line.startswith("Successfully installed "):
            for token in line.removeprefix("Successfully installed ").split():
                parsed = _parse_successfully_installed_token(token)
                if parsed is not None:
                    name, version = parsed
                    installed[name] = version
                    touched.add(name)
            continue
        if re.match(
            r"(?i)^(?:ERROR:\s*)?pip's (?:legacy )?dependency resolver .*dependency conflicts\.",
            line,
        ):
            in_conflict_block = True
            conflicts.append(line)
            continue
        if in_conflict_block and re.match(r"^[A-Za-z0-9_.-]+ .+ requires .+", line):
            conflicts.append(line)
            continue
        path_match = re.match(
            r"(?i)^WARNING:\s+The scripts? (.+?) (?:is|are) installed in '(.+?)' "
            r"which is not on PATH\.",
            line,
        )
        if path_match:
            path_warnings.append(line)
            continue
        if line.startswith("ERROR:"):
            generic_errors.append(line)
    return PipSideEffects(
        touched_packages=tuple(sorted(touched, key=str.casefold)),
        successfully_installed=dict(sorted(installed.items(), key=lambda pair: pair[0].casefold())),
        resolver_conflicts=tuple(conflicts),
        scripts_not_on_path=tuple(path_warnings),
        generic_error_warnings=tuple(generic_errors),
    )


def compact_list_summary(values: Sequence[str], *, singular: str, plural: str) -> str:
    clean_values = [value for value in values if value]
    count = len(clean_values)
    label = singular if count == 1 else plural
    if count == 0:
        return f"0 {plural}"
    if count <= 3:
        return f"{count} {label}: {', '.join(clean_values)}"
    return f"{count} {plural}"


def compact_pip_detail_hint(package_id: str) -> str:
    return (
        "For more pip detail, run: "
        f"py -3 -m pip --disable-pip-version-check show {package_id} "
        "and py -3 -m pip check; if the py launcher is unavailable, use "
        "python -m pip with your intended user Python instead"
    )


def nonzero_count_summary(parts: Sequence[tuple[str, int]], *, zero_message: str = "") -> str:
    visible = [f"{count} {label}" for label, count in parts if count]
    if visible:
        return ", ".join(visible)
    return zero_message


def summarize_manifest_values(values: Sequence[str]) -> str:
    unique = sorted({value for value in values if value})
    if not unique:
        return ""
    return unique[0] if len(unique) == 1 else "mixed"


def parse_winget_show_metadata(
    text: str, *, package_id: str = "", source: str = "", returncode: int = 0, error: str = ""
) -> WingetManifestMetadata:
    """Parse key/value metadata from `winget show`.

    The command emits human-oriented text, not a table. Keep this deliberately
    conservative: unknown wording means missing metadata, never guessed metadata.
    """
    fields: dict[str, str] = {}
    installer_types: set[str] = set()
    scopes: set[str] = set()
    upgrade_behaviors: set[str] = set()
    cleaned_lines = clean_output(text).splitlines()
    for line in cleaned_lines:
        found = re.match(r"^\s*Found\s+(?P<name>.+?)\s+\[(?P<id>[^\]]+)\]", line)
        if found and (
            not package_id
            or found.group("id").strip().casefold() == package_id.casefold()
        ):
            fields.setdefault("name", found.group("name").strip())
            break
    for line in cleaned_lines:
        raw_key, separator, raw_value = line.partition(":")
        label = raw_key.strip()
        if (
            not separator
            or not 2 <= len(label) <= 41
            or not label[0].isascii()
            or not label[0].isalpha()
            or any(not (character.isascii() and (character.isalpha() or character == " ")) for character in label)
        ):
            continue
        key = label.casefold().replace(" ", "")
        value = raw_value.strip()
        if not value:
            continue
        fields.setdefault(key, value)
        normalized = normalized_manifest_value(value)
        if key in {
            "installertype",
            "installertypes",
            "installer",
            "nestedinstallertype",
            "nestedinstallertypes",
        }:
            installer_types.add(normalized)
        elif key == "scope":
            scopes.add(normalized)
        elif key == "upgradebehavior":
            upgrade_behaviors.add(normalized)
    return WingetManifestMetadata(
        package_id=package_id,
        source=source,
        returncode=returncode,
        installer_types=tuple(sorted(installer_types)),
        scopes=tuple(sorted(scopes)),
        upgrade_behaviors=tuple(sorted(upgrade_behaviors)),
        raw_fields=fields,
        error=error,
    )


# ==================== Package model and persisted update evidence ====================

@dataclasses.dataclass(slots=True)
class UpdateItem:
    provider: str
    name: str
    package_id: str
    current: str
    available: str
    source: str = ""
    scope: str = "user"
    requires_admin: bool = False
    selected: bool = True
    status: str = "Ready"
    instance: int = 0
    classification: str = CLASS_SIMPLE_UPGRADE
    guidance: str = ""
    guidance_url: str = ""
    icon_source: str = ""
    installed_for: str = ""
    installed_technology: str = ""
    installed_location: str = ""
    installed_size_kb: int | None = None
    installed_date: str = ""
    installed_timestamp: str = ""
    installed_timestamp_precision: str = ""
    installed_registration_changed_at: str = ""
    installed_registration_changed_at_precision: str = ""
    installed_date_source: str = ""
    installed_date_is_estimate: bool = False
    product_codes: tuple[str, ...] = ()
    metadata_sources: tuple[str, ...] = ()
    launch_app_ids: tuple[str, ...] = ()
    metadata_confidence: str = ""
    publisher: str = ""
    description: str = ""
    architecture: str = ""
    available_technology: str = ""
    available_scope: str = ""
    available_upgrade_behavior: str = ""
    applicability_prediction: str = PREDICTION_ORDINARY
    prediction_confidence: str = ""
    prediction_source: str = ""
    prediction_reasons: tuple[str, ...] = ()
    predicted_hresult: str = ""
    portable_executable: str = ""
    portable_scan_root: str = ""
    portable_detected_by: str = ""
    portable_on_path: bool | None = None
    portable_app_key: str = ""
    portable_publisher: str = ""
    portable_original_filename: str = ""
    portable_homepage: str = ""
    portable_detection_confidence: str = ""
    portable_evidence_score: int = 0
    portable_evidence_reasons: tuple[str, ...] = ()
    portable_format: str = ""
    portable_removal_kind: str = ""
    portable_removal_target: str = ""
    portable_removal_reason: str = ""
    portable_catalog_package_id: str = ""
    portable_catalog_name: str = ""
    portable_catalog_homepage: str = ""
    portable_catalog_download_url: str = ""
    portable_catalog_match_basis: str = ""
    portable_catalog_checked_at: str = ""
    portable_catalog_error: str = ""

    @property
    def key(self) -> str:
        raw = f"{self.provider}|{self.package_id}|{self.scope}|{self.source}|{self.instance}"
        return raw.casefold()

    @property
    def ignore_key(self) -> str:
        return (
            f"{self.provider}:{self.package_id}:{self.scope}:{self.source}:{self.instance}"
        ).casefold()

    @property
    def legacy_ignore_key(self) -> str:
        return f"{self.provider}:{self.package_id}:{self.scope}".casefold()

    @property
    def candidate_key(self) -> str:
        """Identify one exact installed-to-available transition."""
        raw = "\0".join(
            (
                self.provider.casefold(),
                self.package_id.casefold(),
                self.scope.casefold(),
                self.source.casefold(),
                self.current.casefold(),
                self.available.casefold(),
                str(self.instance),
            )
        )
        return hashlib.sha256(raw.encode("utf-8")).hexdigest()

    @property
    def verification_identity_key(self) -> str:
        """Identify one provider registration while deliberately ignoring versions."""

        raw = "\0".join(
            (
                self.provider.casefold(),
                self.package_id.casefold(),
                self.scope.casefold(),
                self.source.casefold(),
                str(self.instance),
            )
        )
        return hashlib.sha256(raw.encode("utf-8")).hexdigest()

    def to_plan_dict(self) -> dict[str, Any]:
        return {
            "provider": self.provider,
            "name": self.name,
            "package_id": self.package_id,
            "current": self.current,
            "available": self.available,
            "source": self.source,
            "scope": self.scope,
            "requires_admin": self.requires_admin,
            "instance": self.instance,
        }

    @classmethod
    def from_plan_dict(cls, value: dict[str, Any]) -> UpdateItem:
        if set(value) != ELEVATION_PLAN_FIELDS:
            raise ValueError("elevation plan item fields do not match the schema")
        for field in ("provider", "name", "package_id", "current", "available", "source", "scope"):
            if not isinstance(value.get(field), str):
                raise ValueError(f"elevation plan field must be a string: {field}")
        requires_admin = value.get("requires_admin", False)
        if not isinstance(requires_admin, bool):
            raise ValueError("elevation plan requires_admin must be boolean")
        raw_instance = value.get("instance", 0)
        if not isinstance(raw_instance, int) or isinstance(raw_instance, bool):
            raise ValueError("elevation plan item instance must be an integer")
        try:
            instance = int(raw_instance)
        except (TypeError, ValueError) as exc:
            raise ValueError("elevation plan item instance must be an integer") from exc
        item = cls(
            provider=str(value.get("provider", "")),
            name=str(value.get("name", "")),
            package_id=str(value.get("package_id", "")),
            current=str(value.get("current", "")),
            available=str(value.get("available", "")),
            source=str(value.get("source", "")),
            scope=str(value.get("scope", "")),
            requires_admin=requires_admin,
            instance=instance,
        )
        if not valid_package_id(item.provider):
            raise ValueError(f"unsafe provider id: {item.provider!r}")
        if not valid_package_id(item.package_id):
            raise ValueError(f"unsafe package id: {item.package_id!r}")
        # Installed evidence is never passed as the upgrade target. Preserve
        # WinGet's bounded-version notation for exact revalidation, not commands.
        if not (valid_version(item.current) or (
            item.provider == "winget" and len(item.current) <= 128
            and re.fullmatch(r"< ?\d+(?:\.\d+)*", item.current)
        )):
            raise ValueError(f"unsafe current version: {item.current!r}")
        if not valid_version(item.available):
            raise ValueError(f"unsafe target version: {item.available!r}")
        if item.source and not valid_provider_source(item.source):
            raise ValueError(f"unsafe provider source: {item.source!r}")
        if item.scope and item.scope not in {"user", "machine"}:
            raise ValueError(f"unsafe item scope: {item.scope!r}")
        if item.instance < 0:
            raise ValueError("elevation plan contains a negative item instance")
        return item


def stable_identity_instances(items: Sequence[UpdateItem]) -> list[UpdateItem]:
    """Assign duplicate ordinals per logical identity instead of global row position."""

    counts: dict[tuple[str, str, str, str], int] = {}
    normalized: list[UpdateItem] = []
    for item in items:
        identity = (
            item.provider.casefold(),
            item.package_id.casefold(),
            item.scope.casefold(),
            item.source.casefold(),
        )
        instance = counts.get(identity, 0)
        counts[identity] = instance + 1
        normalized.append(
            item if item.instance == instance else dataclasses.replace(item, instance=instance)
        )
    return normalized


def strict_numeric_version(value: str) -> tuple[int, ...] | None:
    """Normalize only plain dotted numeric versions, including harmless trailing zeroes."""

    folded = value.strip().casefold()
    if not re.fullmatch(r"v?\d+(?:\.\d+)*", folded):
        return None
    numbers = [int(part) for part in folded.removeprefix("v").split(".")]
    while len(numbers) > 1 and numbers[-1] == 0:
        numbers.pop()
    return tuple(numbers)


def compare_strict_numeric_versions(left: str, right: str) -> int | None:
    """Compare plain numeric versions; return ``None`` for richer provider syntax."""

    left_parts = strict_numeric_version(left)
    right_parts = strict_numeric_version(right)
    if left_parts is None or right_parts is None:
        return None
    width = max(len(left_parts), len(right_parts))
    padded_left = left_parts + (0,) * (width - len(left_parts))
    padded_right = right_parts + (0,) * (width - len(right_parts))
    return (padded_left > padded_right) - (padded_left < padded_right)


KNOWN_PRODUCT_VARIANT_NAMES = {
    ("winget", "anthropic.claude"): "Claude (Desktop app)",
    ("winget", "anthropic.claudecode"): "Claude Code (CLI)",
    ("npm", "@anthropic-ai/claude-code"): "Claude Code (CLI)",
    ("winget", "openai.codex"): "Codex (CLI)",
    ("npm", "@openai/codex"): "Codex (CLI)",
}

# Stable publisher-qualified identity from the WinGet installer manifest:
# microsoft/winget-pkgs manifests/a/Anthropic/Claude/*/Anthropic.Claude.installer.yaml
# This is not a display-name match and does not confer Microsoft Store provenance.
KNOWN_WINGET_PACKAGE_FAMILIES = {"anthropic.claude": "Claude_pzs8sxrjxfjjc"}


def known_product_variant_name(provider: str, package_id: str, name: str) -> str:
    """Disambiguate products whose stable package identities identify their interface."""
    identity = (provider.casefold(), package_id.casefold())
    if alias := KNOWN_PRODUCT_VARIANT_NAMES.get(identity):
        return alias
    if identity[0] == MICROSOFT_STORE_PROVIDER_KEY and identity[1].startswith(
        "msix\\openai.codex_"
    ):
        return "Codex (Desktop app)"
    return name


def apply_known_product_variant_names(items: Sequence[UpdateItem]) -> None:
    for item in items:
        item.name = known_product_variant_name(item.provider, item.package_id, item.name)


@dataclasses.dataclass(frozen=True, slots=True)
class InstalledInventorySnapshot:
    items: tuple[UpdateItem, ...] = ()
    provider_keys: frozenset[str] = frozenset()
    scanned_at: dt.datetime | None = None
    update_observations: Mapping[str, Mapping[str, str]] = dataclasses.field(
        default_factory=dict
    )
    provider_scanned_at: Mapping[str, str] = dataclasses.field(default_factory=dict)
    installation_observations: Mapping[str, Mapping[str, str]] = dataclasses.field(
        default_factory=dict
    )
    provider_started_at: Mapping[str, str] = dataclasses.field(default_factory=dict)


class InstalledInventoryStore:
    """Bounded, account-specific cache of the last complete installed inventory."""

    _tuple_fields = frozenset(
        {
            "product_codes",
            "metadata_sources",
            "launch_app_ids",
            "prediction_reasons",
            "portable_evidence_reasons",
        }
    )
    _bool_fields = frozenset(
        {"requires_admin", "selected", "installed_date_is_estimate"}
    )
    _int_fields = frozenset({"instance", "portable_evidence_score"})
    _field_names = frozenset(field.name for field in dataclasses.fields(UpdateItem))
    _legacy_item_field_names = _field_names - {
        "installed_timestamp",
        "installed_timestamp_precision",
        "installed_registration_changed_at",
        "installed_registration_changed_at_precision",
    }
    _observation_fields = frozenset(
        {
            "provider",
            "package_id",
            "scope",
            "source",
            "available_version",
            "last_absent_at",
            "first_seen_at",
            "last_seen_at",
        }
    )
    _installation_observation_fields = frozenset(
        {
            "provider",
            "package_id",
            "scope",
            "source",
            "version",
            "state",
            "previous_version",
            "transition_kind",
            "lower_bound_at",
            "first_seen_at",
            "last_seen_at",
            "last_absent_at",
        }
    )

    def __init__(self, path: Path | None = None) -> None:
        self.path = path or installed_inventory_cache_path()
        self._lock = threading.RLock()
        self._latest_write_generation = 0
        self.snapshot = InstalledInventorySnapshot()
        self.warning = ""
        self._load()

    @classmethod
    def _item_from_json(cls, value: Any, allowed_providers: Set[str]) -> UpdateItem:
        if not isinstance(value, dict):
            raise ValueError("installed inventory item fields do not match the schema")
        if set(value) in {
            cls._field_names - {"launch_app_ids"},
            cls._legacy_item_field_names - {"launch_app_ids"},
        }:
            value = {**value, "launch_app_ids": []}
        if set(value) == cls._legacy_item_field_names:
            value = {
                **value,
                "installed_timestamp": "",
                "installed_timestamp_precision": (
                    "date" if value.get("installed_date") else ""
                ),
                "installed_registration_changed_at": "",
                "installed_registration_changed_at_precision": "",
            }
        elif set(value) != cls._field_names:
            raise ValueError("installed inventory item fields do not match the schema")
        converted: dict[str, Any] = {}
        for key, raw in value.items():
            if key in cls._tuple_fields:
                if not isinstance(raw, list) or len(raw) > 256:
                    raise ValueError(f"installed inventory field must be a bounded list: {key}")
                if any(
                    not isinstance(entry, str)
                    or len(entry) > INSTALLED_INVENTORY_CACHE_MAX_FIELD_CHARS
                    for entry in raw
                ):
                    raise ValueError(f"installed inventory list contains an invalid value: {key}")
                converted[key] = tuple(raw)
            elif key in cls._bool_fields:
                if not isinstance(raw, bool):
                    raise ValueError(f"installed inventory field must be boolean: {key}")
                converted[key] = raw
            elif key in cls._int_fields:
                if not isinstance(raw, int) or isinstance(raw, bool) or raw < 0:
                    raise ValueError(
                        f"installed inventory field must be a non-negative integer: {key}"
                    )
                converted[key] = raw
            elif key == "installed_size_kb":
                if raw is not None and (
                    not isinstance(raw, int) or isinstance(raw, bool) or raw < 0
                ):
                    raise ValueError("installed inventory size must be non-negative or null")
                converted[key] = raw
            elif key == "portable_on_path":
                if raw is not None and not isinstance(raw, bool):
                    raise ValueError("installed inventory PATH evidence must be boolean or null")
                converted[key] = raw
            else:
                if not isinstance(raw, str) or len(raw) > (
                    INSTALLED_INVENTORY_CACHE_MAX_FIELD_CHARS
                ):
                    raise ValueError(f"installed inventory field must be a bounded string: {key}")
                converted[key] = raw
        item = UpdateItem(**converted)
        if item.provider not in allowed_providers or item.provider == PORTABLE_PROVIDER_KEY:
            raise ValueError("installed inventory item used an unexpected provider")
        if item.classification != CLASS_INVENTORY_ONLY or item.selected:
            raise ValueError("installed inventory cache contained an actionable row")
        if item.installed_timestamp and not wall_clock_timestamp_matches_precision(
            item.installed_timestamp, item.installed_timestamp_precision
        ):
            raise ValueError("installed inventory item timestamp was invalid")
        if item.installed_timestamp_precision and not re.fullmatch(
            r"date|second|fractional-[1-6]", item.installed_timestamp_precision
        ):
            raise ValueError("installed inventory item timestamp precision was invalid")
        if not item.installed_timestamp and item.installed_timestamp_precision not in {
            "",
            "date",
        }:
            raise ValueError("installed inventory item timestamp precision lacked a value")
        if item.installed_registration_changed_at and not (
            wall_clock_timestamp_matches_precision(
                item.installed_registration_changed_at,
                item.installed_registration_changed_at_precision,
            )
        ):
            raise ValueError("installed inventory registration timestamp was invalid")
        if bool(item.installed_registration_changed_at) != bool(
            item.installed_registration_changed_at_precision
        ):
            raise ValueError("installed inventory registration precision lacked a value")
        return item

    def _load(self) -> None:
        try:
            raw = self.path.read_bytes()
            if len(raw) > INSTALLED_INVENTORY_CACHE_MAX_BYTES:
                raise ValueError("installed inventory cache exceeded its size limit")
            payload = loads_strict_json_object(raw, "installed inventory cache")
            legacy_root_fields = {
                "schema",
                "app_version",
                "account_fingerprint",
                "scanned_at",
                "provider_keys",
                "items",
            }
            schema_2_root_fields = legacy_root_fields | {
                "update_observations",
                "provider_scanned_at",
            }
            current_root_fields = schema_2_root_fields | {"installation_observations"}
            schema = payload.get("schema")
            expected_root_fields = (
                legacy_root_fields
                if schema == 1
                else schema_2_root_fields
                if schema == 2
                else current_root_fields | {"provider_started_at"}
                if schema == 5
                else current_root_fields
            )
            if set(payload) != expected_root_fields:
                raise ValueError("installed inventory cache fields do not match the schema")
            if schema not in {
                INSTALLED_INVENTORY_CACHE_SCHEMA,
                *INSTALLED_INVENTORY_CACHE_LEGACY_SCHEMAS,
            }:
                raise ValueError("installed inventory cache uses an unsupported schema")
            app_version = payload.get("app_version")
            if not isinstance(app_version, str) or len(app_version) > 64:
                raise ValueError("installed inventory cache app version was invalid")
            if payload.get("account_fingerprint") != current_account_fingerprint():
                raise ValueError("installed inventory cache belongs to a different account")
            raw_provider_keys = payload.get("provider_keys")
            if (
                not isinstance(raw_provider_keys, list)
                or len(raw_provider_keys) > 64
                or any(
                    not isinstance(key, str)
                    or not key
                    or len(key) > 128
                    for key in raw_provider_keys
                )
            ):
                raise ValueError("installed inventory provider list was invalid")
            provider_keys = frozenset(raw_provider_keys)
            if len(provider_keys) != len(raw_provider_keys):
                raise ValueError("installed inventory provider list contained duplicates")
            raw_items = payload.get("items")
            if (
                not isinstance(raw_items, list)
                or len(raw_items) > INSTALLED_INVENTORY_CACHE_MAX_ITEMS
            ):
                raise ValueError("installed inventory item list was invalid")
            items = tuple(
                self._item_from_json(value, provider_keys) for value in raw_items
            )
            if len({item.key for item in items}) != len(items):
                raise ValueError("installed inventory cache contained duplicate item identities")
            raw_scanned_at = payload.get("scanned_at")
            if not isinstance(raw_scanned_at, str) or len(raw_scanned_at) > 64:
                raise ValueError("installed inventory timestamp was invalid")
            scanned_at = dt.datetime.fromisoformat(raw_scanned_at)
            if schema == INSTALLED_INVENTORY_CACHE_SCHEMA and scanned_at.tzinfo is None:
                raise ValueError("installed inventory timestamp lacked a timezone")
            raw_observations = payload.get("update_observations", {})
            if not isinstance(raw_observations, dict) or len(raw_observations) > 10_000:
                raise ValueError("installed inventory observations were invalid")
            observations: dict[str, dict[str, str]] = {}
            for key, record in raw_observations.items():
                if (
                    not isinstance(key, str)
                    or not SHA256_RE.fullmatch(key)
                    or not isinstance(record, dict)
                    or set(record) != self._observation_fields
                    or any(
                        not isinstance(value, str)
                        or len(value) > INSTALLED_INVENTORY_CACHE_MAX_FIELD_CHARS
                        for value in record.values()
                    )
                ):
                    raise ValueError("installed inventory observation record was invalid")
                if any(
                    value and not valid_wall_clock_instant(
                        value,
                        require_timezone=(schema == INSTALLED_INVENTORY_CACHE_SCHEMA),
                    )
                    for value in (
                        record["last_absent_at"],
                        record["first_seen_at"],
                        record["last_seen_at"],
                    )
                ):
                    raise ValueError("installed inventory observation timestamp was invalid")
                observations[key] = dict(record)
            raw_provider_scanned_at = payload.get("provider_scanned_at", {})
            if not isinstance(raw_provider_scanned_at, dict) or any(
                key not in provider_keys
                or not isinstance(value, str)
                or len(value) > 64
                for key, value in raw_provider_scanned_at.items()
            ):
                raise ValueError("installed inventory provider timestamps were invalid")
            if any(
                not valid_wall_clock_instant(
                    value,
                    require_timezone=(schema == INSTALLED_INVENTORY_CACHE_SCHEMA),
                )
                for value in raw_provider_scanned_at.values()
            ):
                raise ValueError("installed inventory provider timestamp was invalid")
            provider_scanned_at = {
                key: value for key, value in raw_provider_scanned_at.items()
            }
            provider_started_at = payload.get("provider_started_at", {})
            if not isinstance(provider_started_at, dict) or any(
                key not in provider_keys or not isinstance(value, str)
                or len(value) > 64 or not valid_wall_clock_instant(value, require_timezone=True)
                or wall_clock_order_key(value) > wall_clock_order_key(provider_scanned_at.get(key, ""))
                for key, value in provider_started_at.items()
            ):
                raise ValueError("installed inventory observation intervals were invalid")
            if schema == 1:
                provider_scanned_at = {
                    key: raw_scanned_at
                    for key in provider_keys
                }
            raw_installation_observations = payload.get("installation_observations", {})
            if (
                not isinstance(raw_installation_observations, dict)
                or len(raw_installation_observations) > INSTALLED_INVENTORY_CACHE_MAX_ITEMS
            ):
                raise ValueError("installed lifecycle observations were invalid")
            installation_observations: dict[str, dict[str, str]] = {}
            for key, record in raw_installation_observations.items():
                if (
                    not isinstance(key, str)
                    or not SHA256_RE.fullmatch(key)
                    or not isinstance(record, dict)
                    or set(record) != self._installation_observation_fields
                    or any(
                        not isinstance(value, str)
                        or len(value) > INSTALLED_INVENTORY_CACHE_MAX_FIELD_CHARS
                        for value in record.values()
                    )
                    or record.get("provider") not in provider_keys
                    or record.get("state") not in {"present", "absent", "ambiguous"}
                ):
                    raise ValueError("installed lifecycle observation record was invalid")
                if any(
                    value and not valid_wall_clock_instant(
                        value,
                        require_timezone=(schema == INSTALLED_INVENTORY_CACHE_SCHEMA),
                    )
                    for value in (
                        record["lower_bound_at"],
                        record["first_seen_at"],
                        record["last_seen_at"],
                        record["last_absent_at"],
                    )
                ):
                    raise ValueError("installed lifecycle observation timestamp was invalid")
                installation_observations[key] = dict(record)
            self.snapshot = InstalledInventorySnapshot(
                items=items,
                provider_keys=provider_keys,
                scanned_at=scanned_at,
                update_observations=observations,
                provider_scanned_at=provider_scanned_at,
                installation_observations=installation_observations,
                provider_started_at=dict(provider_started_at),
            )
        except FileNotFoundError:
            return
        except (OSError, TypeError, ValueError) as exc:
            self.warning = f"{type(exc).__name__}: {exc}"

    def items_for(self, provider_keys: Set[str]) -> tuple[UpdateItem, ...]:
        """Return detached rows only for providers still enabled in this session."""

        allowed = set(provider_keys)
        with self._lock:
            items = tuple(
                dataclasses.replace(item)
                for item in self.snapshot.items
                if item.provider in allowed
            )
        apply_known_product_variant_names(items)
        return items

    def replace(
        self,
        items: Sequence[UpdateItem],
        provider_keys: Set[str],
        scanned_at: dt.datetime,
        update_observations: Mapping[str, Mapping[str, str]],
        provider_scanned_at: Mapping[str, str],
        installation_observations: Mapping[str, Mapping[str, str]] | None = None,
        *,
        provider_started_at: Mapping[str, str] | None = None,
        write_generation: int = 0,
    ) -> bool:
        with self._lock:
            if scanned_at.tzinfo is None:
                raise ValueError("installed inventory timestamp must include a timezone")
            if write_generation and write_generation < self._latest_write_generation:
                return False
            if any(
                item.provider not in provider_keys
                or item.provider == PORTABLE_PROVIDER_KEY
                or item.classification != CLASS_INVENTORY_ONLY
                for item in items
            ):
                raise ValueError("installed inventory cache input contained an invalid row")
            clean_items = tuple(
                dataclasses.replace(item, selected=False)
                for item in items
            )
            if len(clean_items) > INSTALLED_INVENTORY_CACHE_MAX_ITEMS:
                raise ValueError("installed inventory exceeded its item limit")
            if len({item.key for item in clean_items}) != len(clean_items):
                raise ValueError("installed inventory contained duplicate item identities")
            clean_observations = {
                str(key): {str(field): str(value) for field, value in record.items()}
                for key, record in update_observations.items()
            }
            if len(clean_observations) > 10_000 or any(
                not SHA256_RE.fullmatch(key)
                or set(record) != self._observation_fields
                or any(
                    len(value) > INSTALLED_INVENTORY_CACHE_MAX_FIELD_CHARS
                    for value in record.values()
                )
                or any(
                    value and not valid_wall_clock_instant(value)
                    for value in (
                        record["last_absent_at"],
                        record["first_seen_at"],
                        record["last_seen_at"],
                    )
                )
                for key, record in clean_observations.items()
            ):
                raise ValueError("installed inventory observations were invalid")
            clean_provider_scanned_at = {
                str(key): str(value) for key, value in provider_scanned_at.items()
            }
            if set(clean_provider_scanned_at) != provider_keys or any(
                not value or len(value) > 64
                or not valid_wall_clock_instant(value)
                for value in clean_provider_scanned_at.values()
            ):
                raise ValueError("installed inventory provider timestamps were invalid")
            clean_installation_observations = {
                str(key): {str(field): str(value) for field, value in record.items()}
                for key, record in (installation_observations or {}).items()
            }
            if len(clean_installation_observations) > INSTALLED_INVENTORY_CACHE_MAX_ITEMS or any(
                not SHA256_RE.fullmatch(key)
                or set(record) != self._installation_observation_fields
                or record.get("provider") not in provider_keys
                or record.get("state") not in {"present", "absent", "ambiguous"}
                or any(
                    len(value) > INSTALLED_INVENTORY_CACHE_MAX_FIELD_CHARS
                    for value in record.values()
                )
                or any(
                    value and not valid_wall_clock_instant(value)
                    for value in (
                        record["lower_bound_at"],
                        record["first_seen_at"],
                        record["last_seen_at"],
                        record["last_absent_at"],
                    )
                )
                for key, record in clean_installation_observations.items()
            ):
                raise ValueError("installed lifecycle observations were invalid")
            clean_provider_started_at = dict(provider_started_at or {})
            if any(
                key not in provider_keys or not isinstance(value, str)
                or len(value) > 64 or not valid_wall_clock_instant(value, require_timezone=True)
                or wall_clock_order_key(value) > wall_clock_order_key(clean_provider_scanned_at[key])
                for key, value in clean_provider_started_at.items()
            ):
                raise ValueError("installed inventory observation intervals were invalid")
            payload = {
                "schema": INSTALLED_INVENTORY_CACHE_SCHEMA,
                "app_version": APP_VERSION,
                "account_fingerprint": current_account_fingerprint(),
                "scanned_at": datetime_storage_timestamp(scanned_at),
                "provider_keys": sorted(provider_keys),
                # Rows contain only scalars and tuples of strings. The JSON
                # encoder handles those directly; recursive deepcopy adds work
                # while the GUI shares this interpreter's GIL.
                "items": [
                    {name: getattr(item, name) for name in self._field_names}
                    for item in clean_items
                ],
                "update_observations": clean_observations,
                "provider_scanned_at": clean_provider_scanned_at,
                "provider_started_at": clean_provider_started_at,
                "installation_observations": clean_installation_observations,
            }
            text = json.dumps(
                payload,
                ensure_ascii=False,
                sort_keys=True,
                separators=(",", ":"),
                allow_nan=False,
            )
            atomic_write_text(
                self.path,
                text,
                max_bytes=INSTALLED_INVENTORY_CACHE_MAX_BYTES,
            )
            self.snapshot = InstalledInventorySnapshot(
                items=clean_items,
                provider_keys=frozenset(provider_keys),
                scanned_at=scanned_at,
                update_observations=clean_observations,
                provider_scanned_at=clean_provider_scanned_at,
                installation_observations=clean_installation_observations,
                provider_started_at=clean_provider_started_at,
            )
            self.warning = ""
            if write_generation:
                self._latest_write_generation = write_generation
            return True


def update_versions_equivalent(left: str, right: str) -> bool:
    """Compare a provider's target versions without overclaiming nonnumeric aliases."""

    return left.casefold() == right.casefold() or compare_strict_numeric_versions(
        left, right
    ) == 0


def update_observation_identity_key(item: UpdateItem) -> str:
    """Identify an offered package independently of provider display-source labels."""

    raw = "\0".join(
        (
            item.provider.casefold(),
            item.package_id.casefold(),
            item.scope.casefold(),
        )
    )
    return hashlib.sha256(raw.encode("utf-8")).hexdigest()


def installed_version_is_observable(version: str) -> bool:
    """Reject placeholders that cannot prove an installed-version transition."""

    return version.strip().casefold() not in {
        "",
        "?",
        "unknown",
        "installed",
        "n/a",
        "(not available)",
        "checking…",
        "checking...",
    }


def evolve_installation_observations(
    previous: InstalledInventorySnapshot,
    current_items: Sequence[UpdateItem],
    provider_keys: Set[str],
    fresh_provider_keys: Set[str],
    provider_scanned_at: Mapping[str, str],
) -> dict[str, dict[str, str]]:
    """Remember installed-version transitions without another query or write.

    Identity deliberately ignores display source and instance counters. If that
    relaxed identity is not unique within either inventory, no inference is made.
    Only providers with a completed fresh inventory may advance observations.
    """

    fresh = set(fresh_provider_keys).intersection(provider_keys)

    def unique_items(items: Sequence[UpdateItem]) -> dict[str, UpdateItem]:
        grouped: dict[str, list[UpdateItem]] = {}
        for item in items:
            if item.provider in provider_keys and item.provider != PORTABLE_PROVIDER_KEY:
                grouped.setdefault(update_observation_identity_key(item), []).append(item)
        return {key: values[0] for key, values in grouped.items() if len(values) == 1}

    current = unique_items(current_items)
    previous_items = unique_items(previous.items)
    ambiguous_previous = {
        update_observation_identity_key(item) for item in previous.items
        if item.provider in provider_keys
    }.difference(previous_items)
    ambiguous_current = {
        update_observation_identity_key(item)
        for item in current_items
        if item.provider in provider_keys
    }.difference(current)
    evolved = {
        key: dict(record)
        for key, record in previous.installation_observations.items()
        if record.get("provider") in provider_keys
        and record.get("provider") not in fresh
    }

    for identity_key, item in current.items():
        prior = previous.installation_observations.get(identity_key)
        if item.provider not in fresh:
            continue
        if not installed_version_is_observable(item.current):
            if isinstance(prior, Mapping):
                evolved[identity_key] = dict(prior)
            continue
        observed_at = str(provider_scanned_at.get(item.provider, ""))
        if not observed_at:
            if isinstance(prior, Mapping):
                evolved[identity_key] = dict(prior)
            continue
        prior_item = previous_items.get(identity_key)
        prior_start = str(previous.provider_started_at.get(item.provider, ""))
        continuity = bool(
            prior_start and identity_key not in ambiguous_previous
            and (prior_item is None or (
                prior_item.key == item.key and installed_version_is_observable(prior_item.current)
            ))
            and (not isinstance(prior, Mapping) or prior.get("state") != "ambiguous")
        )
        if not continuity:
            prior = None
            prior_item = None
        elif isinstance(prior, Mapping) and prior_item is not None and (
            prior.get("state") != "present"
            or not update_versions_equivalent(str(prior.get("version", "")), prior_item.current)
            or str(prior.get("source", "")).casefold() != item.source.casefold()
        ):
            # Recovered historical evidence need not describe the previous rows.
            prior = None
        previous_version = ""
        transition_kind = "baseline"
        lower_bound_at = ""
        first_seen_at = observed_at
        last_absent_at = ""
        if isinstance(prior, Mapping):
            prior_state = str(prior.get("state", ""))
            prior_version = str(prior.get("version", ""))
            last_absent_at = str(prior.get("last_absent_at", ""))
            if prior_state == "present" and update_versions_equivalent(
                prior_version, item.current
            ):
                previous_version = str(prior.get("previous_version", ""))
                transition_kind = str(prior.get("transition_kind", "baseline"))
                lower_bound_at = str(prior.get("lower_bound_at", ""))
                first_seen_at = str(prior.get("first_seen_at", "")) or observed_at
            elif prior_state == "absent":
                previous_version = prior_version
                transition_kind = "installed-or-reappeared"
                lower_bound_at = prior_start
            elif installed_version_is_observable(prior_version):
                previous_version = prior_version
                transition_kind = "version-changed"
                lower_bound_at = prior_start
        elif prior_item is not None:
            prior_at = str(previous.provider_scanned_at.get(item.provider, ""))
            if update_versions_equivalent(prior_item.current, item.current):
                first_seen_at = prior_at or observed_at
            elif installed_version_is_observable(prior_item.current):
                previous_version = prior_item.current
                transition_kind = "version-changed"
                lower_bound_at = prior_start
        elif (
            continuity and item.provider in previous.provider_keys
        ):
            transition_kind = "installed-or-reappeared"
            lower_bound_at = prior_start
            last_absent_at = lower_bound_at
        evolved[identity_key] = {
            "provider": item.provider,
            "package_id": item.package_id,
            "scope": item.scope,
            "source": item.source,
            "version": item.current,
            "state": "present",
            "previous_version": previous_version,
            "transition_kind": transition_kind,
            "lower_bound_at": lower_bound_at,
            "first_seen_at": first_seen_at,
            "last_seen_at": observed_at,
            "last_absent_at": last_absent_at,
        }

    for item in current_items:
        identity_key = update_observation_identity_key(item)
        if item.provider in fresh and identity_key in ambiguous_current:
            evolved[identity_key] = {
                field: "" for field in InstalledInventoryStore._installation_observation_fields
            }
            evolved[identity_key].update(
                provider=item.provider, package_id=item.package_id, scope=item.scope,
                source=item.source, state="ambiguous", transition_kind="baseline",
            )
    absent: list[tuple[str, dict[str, str]]] = []
    current_identities = set(current).union(ambiguous_current)
    for identity_key, prior in previous.installation_observations.items():
        provider = str(prior.get("provider", ""))
        if provider not in fresh or identity_key in current_identities:
            continue
        observed_at = str(provider_scanned_at.get(provider, ""))
        if not observed_at:
            continue
        record = {str(key): str(value) for key, value in prior.items()}
        record["state"] = "absent"
        record["last_absent_at"] = observed_at
        absent.append((identity_key, record))
    absent.sort(
        key=lambda pair: wall_clock_order_key(pair[1].get("last_absent_at", "")),
        reverse=True,
    )
    for identity_key, record in absent:
        if len(evolved) >= INSTALLED_INVENTORY_CACHE_MAX_ITEMS:
            break
        evolved[identity_key] = record
    return evolved


def evolve_update_observations(
    previous: InstalledInventorySnapshot,
    current_updates: Sequence[UpdateItem],
    provider_keys: Set[str],
    scanned_at: dt.datetime,
    provider_scanned_at: Mapping[str, str],
) -> dict[str, dict[str, str]]:
    """Carry compact first-seen windows inside the existing inventory-cache write.

    A complete earlier inventory for the same provider and installed identity proves
    that a newly observed target was not offered at that earlier scan. Repeated scans
    of the same target retain its original boundary; no extra probe or file write is
    introduced.
    """

    scan_completed_at = datetime_storage_timestamp(scanned_at)
    def grouped_items(items: Sequence[UpdateItem]) -> dict[str, list[UpdateItem]]:
        grouped: dict[str, list[UpdateItem]] = {}
        for item in items:
            grouped.setdefault(update_observation_identity_key(item), []).append(item)
        return grouped

    previous_groups = grouped_items(previous.items)
    current_groups = grouped_items(current_updates)
    evolved: dict[str, dict[str, str]] = {}
    for item in current_updates:
        if item.provider not in provider_keys or not item.available.strip():
            continue
        observed_at = str(provider_scanned_at.get(item.provider, scan_completed_at))
        identity_key = update_observation_identity_key(item)
        prior = previous.update_observations.get(identity_key, {})
        prior_items = previous_groups.get(identity_key, [])
        continuity = bool(
            previous.provider_started_at.get(item.provider)
            and len(prior_items) == 1 and prior_items[0].key == item.key
            and len(current_groups[identity_key]) == 1
        )
        if not continuity or (prior and not prior.get("available_version")):
            prior = {}
            continuity = False
        same_prior_target = bool(prior) and update_versions_equivalent(
            str(prior.get("available_version", "")), item.available
        )
        prior_scan_proves_absence = bool(
            continuity
            and item.provider in previous.provider_keys
            and not same_prior_target
        )
        evolved[identity_key] = {
            "provider": item.provider,
            "package_id": item.package_id,
            "scope": item.scope,
            "source": item.source,
            "available_version": item.available if len(current_groups[identity_key]) == 1 else "",
            "last_absent_at": (
                str(prior.get("last_absent_at", ""))
                if same_prior_target
                else str(previous.provider_started_at.get(item.provider, ""))
                if prior_scan_proves_absence
                else ""
            ),
            "first_seen_at": (
                str(prior.get("first_seen_at", "")) or observed_at
                if same_prior_target
                else observed_at
            ),
            "last_seen_at": observed_at,
        }
    return evolved


def replace_inventory_provider_rows(
    existing: Mapping[str, UpdateItem],
    incoming: Sequence[UpdateItem],
    provider_keys: Set[str],
) -> dict[str, UpdateItem]:
    """Atomically replace complete provider batches in an installed inventory."""

    replaced = {
        key: item for key, item in existing.items() if item.provider not in provider_keys
    }
    for item in incoming:
        if item.provider not in provider_keys:
            raise ValueError("inventory batch contained a row from another provider")
        if item.classification != CLASS_INVENTORY_ONLY:
            raise ValueError("inventory batch contained an actionable row")
        replaced[item.key] = item
    return replaced


def apply_winget_package_policy(item: UpdateItem) -> UpdateItem:
    """Attach narrowly verified package guidance without weakening identity holds."""
    if item.provider not in {"winget", MICROSOFT_STORE_PROVIDER_KEY}:
        return item
    policy = WINGET_PACKAGE_POLICIES.get(item.package_id.casefold())
    if not policy:
        return item
    policy_guidance = str(policy.get("guidance", "")).strip()
    if policy_guidance:
        item.guidance = " ".join(part for part in (item.guidance, policy_guidance) if part)
    item.guidance_url = str(policy.get("guidance_url", ""))
    if item.classification == CLASS_SIMPLE_UPGRADE:
        item.classification = str(policy["classification"])
        item.status = str(policy["status"])
        if policy.get("suppress_bulk"):
            item.selected = False
    return item


def installed_scope_for_prediction(item: UpdateItem) -> str:
    if item.installed_for == "current-user":
        return "user"
    if item.installed_for == "machine":
        return "machine"
    return item.scope if item.scope in {"user", "machine"} else ""


def compatible_winget_installer_technology(
    installed_technology: str, available_types: set[str]
) -> bool:
    """Return whether a manifest installer family can service an installed app.

    Registry technology describes the installed registration, while a WinGet
    manifest describes the current delivery container. Vendor EXE bootstrappers
    commonly service MSI registrations (Adobe Reader is one example), and the
    reverse transition can also be a valid desktop upgrade. Treat those desktop
    families as compatible after WinGet has listed the exact upgrade. Genuine
    desktop-to-AppX/MSIX migrations are classified separately before this
    helper is consulted.
    """
    installed = installed_technology.casefold().strip()
    if not installed or installed in {"unknown", "mixed"} or not available_types:
        return True
    normalized_available = {
        re.sub(r"[^a-z0-9]+", "-", value.casefold()).strip("-")
        for value in available_types
    }
    desktop_installer_types = {
        "exe",
        "inno",
        "inno-setup",
        "nullsoft",
        "nsis",
        "burn",
        "wix",
        "wix-bundle",
        "wixbundle",
        "msi",
        "msi-zip",
        "portable",
        "portable-zip",
        "zip",
    }
    if installed in {"msi", "exe"} and normalized_available <= desktop_installer_types:
        return True
    if installed in {"appx", "msix", "appxbundle", "msixbundle"}:
        return bool(normalized_available & {"appx", "msix", "appxbundle", "msixbundle"})
    return installed in normalized_available


def set_applicability_prediction(
    item: UpdateItem,
    prediction: str,
    *,
    confidence: str,
    source: str,
    reasons: Sequence[str],
    predicted_hresult: str = "",
    classification: str | None = None,
    status: str | None = None,
    guidance: str | None = None,
) -> UpdateItem:
    normalized_reasons = tuple(reason.strip() for reason in reasons if reason.strip())
    if prediction not in VALID_APPLICABILITY_PREDICTIONS:
        raise ValueError(f"unknown applicability prediction: {prediction!r}")
    if confidence not in VALID_PREDICTION_CONFIDENCES:
        raise ValueError(f"unknown prediction confidence: {confidence!r}")
    if not source.strip():
        raise ValueError("prediction source must not be empty")
    if not normalized_reasons:
        raise ValueError("prediction must include at least one evidence reason")
    if predicted_hresult and not re.fullmatch(r"0x[0-9A-Fa-f]{8}", predicted_hresult):
        raise ValueError(f"prediction HRESULT is malformed: {predicted_hresult!r}")
    item.applicability_prediction = prediction
    item.prediction_confidence = confidence
    item.prediction_source = source
    item.prediction_reasons = normalized_reasons
    item.predicted_hresult = predicted_hresult
    if classification is not None:
        item.classification = classification
    if status is not None:
        item.status = status
    if guidance:
        item.guidance = " ".join(part for part in (item.guidance, guidance) if part)
    if prediction != PREDICTION_ORDINARY:
        item.selected = False
    return item


def prefer_stable_manifest_name(item: UpdateItem, manifest: WingetManifestMetadata) -> None:
    manifest_name = str(manifest.raw_fields.get("name", "")).strip()
    if not manifest_name or manifest_name.casefold() == item.name.casefold():
        return
    folded_name = item.name.casefold()
    folded_version = item.current.casefold().strip()
    if folded_version and (
        folded_name.endswith(folded_version)
        or f" version {folded_version}" in folded_name
    ):
        item.name = manifest_name


def apply_winget_preflight_prediction(
    item: UpdateItem, manifest: WingetManifestMetadata | None
) -> UpdateItem:
    """Classify likely WinGet outcome without changing execution commands."""
    if item.provider != "winget":
        return item
    reasons: list[str] = []
    source_parts: list[str] = []
    if manifest is not None:
        prefer_stable_manifest_name(item, manifest)
        item.available_technology = manifest.installer_type_summary
        item.available_scope = manifest.scope_summary
        item.available_upgrade_behavior = manifest.upgrade_behavior_summary
        if manifest.returncode == 0:
            source_parts.append("winget-show")
        elif manifest.error:
            reasons.append(f"winget-show failed: {manifest.error}")
    policy = WINGET_PACKAGE_POLICIES.get(item.package_id.casefold())
    if item.installed_for or item.installed_technology:
        source_parts.append("registry-heuristic")
    if policy:
        source_parts.append("policy")
        reasons.append(f"policy:{item.package_id}")

    prediction_source = "+".join(dict.fromkeys(source_parts)) or "inventory"
    installed_scope = installed_scope_for_prediction(item)
    installed_technology = item.installed_technology.casefold()
    available_types = set(manifest.installer_types if manifest is not None else ())
    available_scopes = set(manifest.scopes if manifest is not None else ())

    if item.source.casefold() == "msstore" and item.classification in {
        CLASS_AMBIGUOUS_IDENTITY,
        CLASS_VENDOR_MANAGED,
    }:
        return set_applicability_prediction(
            item,
            PREDICTION_STORE_AMBIGUOUS,
            confidence="high",
            source=prediction_source,
            reasons=[*reasons, "store entry does not identify an independently serviceable app"],
            classification=CLASS_AMBIGUOUS_IDENTITY,
            status="Serviced by another app",
            guidance=(
                "This Store/catalog entry is serviced by its owning app. WinDevPilot "
                "shows it for visibility but does not treat it as a normal update."
            ),
        )

    if item.classification == CLASS_DUPLICATE_INSTALL:
        return set_applicability_prediction(
            item,
            PREDICTION_DUPLICATE_RESOLUTION,
            confidence="high" if item.installed_for else "medium",
            source=prediction_source,
            reasons=[*reasons, "same package is visible in multiple install scopes"],
            classification=CLASS_DUPLICATE_INSTALL,
            status="Installed twice",
            guidance=(
                "Both current-user and machine registrations exist. Resolve the "
                "duplicate before expecting an in-place WinGet update."
            ),
        )

    if policy and item.classification == CLASS_VENDOR_MANAGED:
        return set_applicability_prediction(
            item,
            PREDICTION_VENDOR_MANAGED,
            confidence="high",
            source=prediction_source,
            reasons=reasons,
            predicted_hresult="0x8A15002B",
            classification=CLASS_VENDOR_MANAGED,
            status="Updates itself",
            guidance=(
                "This app's vendor updater is the safer update path. A WinGet probe "
                "is expected to be diagnostic rather than successful."
            ),
        )
    if policy and item.classification == CLASS_MIGRATION_REQUIRED:
        return set_applicability_prediction(
            item,
            PREDICTION_MIGRATION_REQUIRED,
            confidence="high",
            source=prediction_source,
            reasons=reasons,
            predicted_hresult="0x8A15008E",
            classification=CLASS_MIGRATION_REQUIRED,
            status=str(policy.get("status", "Needs migration")),
            guidance="Use Details for the guided migration path instead of retrying silently.",
        )
    if policy and item.classification == CLASS_MANUAL_REVIEW:
        return set_applicability_prediction(
            item,
            PREDICTION_UNKNOWN,
            confidence="medium",
            source=prediction_source,
            reasons=reasons,
            classification=CLASS_MANUAL_REVIEW,
            status=str(policy.get("status", "Review manually")),
        )

    if installed_technology in {"msi", "exe"} and available_types & {
        "appx",
        "appxbundle",
        "msix",
        "msixbundle",
    }:
        return set_applicability_prediction(
            item,
            PREDICTION_MIGRATION_REQUIRED,
            confidence="high",
            source=prediction_source,
            reasons=[
                *reasons,
                f"installed technology {installed_technology} vs available {sorted(available_types)}",
            ],
            predicted_hresult="0x8A15008E",
            classification=CLASS_MIGRATION_REQUIRED,
            status="Needs migration",
            guidance=(
                "The available package uses a different install technology. WinGet "
                "cannot do this as an in-place upgrade; use guided migration details."
            ),
        )

    if installed_scope and available_scopes and installed_scope not in available_scopes:
        return set_applicability_prediction(
            item,
            PREDICTION_NOT_APPLICABLE,
            confidence="high",
            source=prediction_source,
            reasons=[
                *reasons,
                f"installed scope {installed_scope} not in available scopes {sorted(available_scopes)}",
            ],
            predicted_hresult="0x8A15002B",
            classification=CLASS_SCOPE_OR_APPLICABILITY,
            status="Not updatable here",
            guidance=(
                "WinGet lists a newer version, but the manifest scope does not match "
                "this installed registration. Retrying is expected to return no "
                "applicable update."
            ),
        )

    if (
        installed_technology
        and available_types
        and not compatible_winget_installer_technology(installed_technology, available_types)
    ):
        return set_applicability_prediction(
            item,
            PREDICTION_NOT_APPLICABLE,
            confidence="medium",
            source=prediction_source,
            reasons=[
                *reasons,
                f"installed technology {installed_technology} differs from manifest {sorted(available_types)}",
            ],
            predicted_hresult="0x8A15002B",
            classification=CLASS_SCOPE_OR_APPLICABILITY,
            status="Not updatable here",
            guidance=(
                "The available installer technology does not appear to match the "
                "installed registration."
            ),
        )

    if (
        manifest is not None
        and manifest.returncode == 0
        and (item.installed_for or item.installed_technology)
    ):
        return set_applicability_prediction(
            item,
            PREDICTION_ORDINARY,
            confidence="medium",
            source=prediction_source,
            reasons=[
                *reasons,
                "WinGet listed the exact upgrade and no hard scope or migration conflict was detected",
            ],
            status="Ready"
            if item.classification == CLASS_SIMPLE_UPGRADE
            and item.status in {"Checking details…", "Review - manifest unavailable"}
            else None,
        )

    return set_applicability_prediction(
        item,
        PREDICTION_UNKNOWN,
        confidence="low",
        source=prediction_source,
        reasons=[*reasons, "insufficient manifest or installed-identity evidence"],
        classification=CLASS_MANUAL_REVIEW if item.classification == CLASS_SIMPLE_UPGRADE else None,
        status="Review - manifest unavailable"
        if item.classification == CLASS_SIMPLE_UPGRADE
        else None,
    )


def powershell_preview_migration_guidance(item: UpdateItem) -> str:
    product_code = item.product_codes[0] if item.product_codes else ""
    lines = [
        "PowerShell Preview MSI -> MSIX guided migration",
        "",
        "Facts:",
        "- WinGet cannot update this package in place because the installed package is MSI",
        "  and the available package is MSIX/Appx.",
        "- The MSIX install is per-user. Review remoting/SYSTEM/all-users implications",
        "  before removing the machine MSI.",
        "",
        "Phase 1 - install the MSIX as the signed-in user:",
        (
            "winget install --id Microsoft.PowerShell.Preview --exact --source winget "
            "--scope user --silent --disable-interactivity "
            "--accept-source-agreements --accept-package-agreements"
        ),
        "",
        "Phase 2 - verify before uninstalling MSI:",
        'pwsh-preview -NoLogo -NoProfile -Command "$PSVersionTable.PSVersion"',
        "",
    ]
    if product_code:
        lines.extend(
            [
                "Phase 3 - optional elevated MSI removal after verification:",
                f"msiexec.exe /x {product_code} /qn /norestart",
                "",
                "If anything looks wrong, stop before Phase 3 and keep the existing MSI.",
            ]
        )
    else:
        lines.extend(
            [
                "Phase 3 - MSI removal:",
                "No proven MSI product code was captured, so WinDevPilot is not "
                "suggesting an uninstall command.",
                "",
                "Stop here and inspect Windows Apps & Features or the installer logs manually.",
            ]
        )
    return "\n".join(lines)


def is_powershell_preview_msi_migration(item: UpdateItem) -> bool:
    return (
        item.provider == "winget"
        and item.package_id.casefold() == "microsoft.powershell.preview"
        and item.classification == CLASS_MIGRATION_REQUIRED
        and item.installed_technology.casefold() == "msi"
    )


def generic_migration_guidance(item: UpdateItem) -> str:
    return "\n".join(
        [
            "Manual migration required",
            "",
            "WinDevPilot classified this as an installer-technology migration, not a "
            "normal in-place update.",
            (
                f"Installed technology: {item.installed_technology or 'unknown'}; "
                f"available technology: {item.available_technology or 'unknown'}."
            ),
            "",
            "Review the package/vendor guidance before uninstalling or reinstalling. "
            "WinDevPilot does not provide product-specific commands for this package.",
        ]
    )


def update_scan_delta(
    previous: Sequence[UpdateItem], current: Sequence[UpdateItem]
) -> dict[str, int]:
    """Summarize meaningful changes between two completed update scans."""

    previous_by_key = {item.key: item for item in previous}
    current_by_key = {item.key: item for item in current}
    shared = previous_by_key.keys() & current_by_key.keys()
    return {
        "new": len(current_by_key.keys() - previous_by_key.keys()),
        "resolved": len(previous_by_key.keys() - current_by_key.keys()),
        "target_changed": sum(
            previous_by_key[key].available != current_by_key[key].available for key in shared
        ),
    }


# ==================== Package-manager providers ====================

class Provider(ABC):
    key: ClassVar[str] = "provider"
    label: ClassVar[str] = "Provider"
    executable: ClassVar[str] = ""
    default_enabled: ClassVar[bool] = True
    configurable: ClassVar[bool] = True
    elevation_allowed: ClassVar[bool] = False
    success_codes: ClassVar[frozenset[int]] = frozenset({0})
    already_current_codes: ClassVar[frozenset[int]] = frozenset()
    not_applicable_codes: ClassVar[frozenset[int]] = frozenset()
    canceled_codes: ClassVar[frozenset[int]] = frozenset()
    reboot_codes: ClassVar[frozenset[int]] = frozenset()
    note_by_code: ClassVar[Mapping[int, str]] = {}

    def __init__(self) -> None:
        self.warnings: list[str] = []
        self.suppressed_updates: list[dict[str, Any]] = []
        self.phase_incomplete_reasons: list[str] = []
        self.debug_mode = False

    def mark_phase_incomplete(self, reason: str) -> None:
        reason = str(reason).strip()
        if reason and reason not in self.phase_incomplete_reasons:
            self.phase_incomplete_reasons.append(reason)

    def available(self) -> bool:
        return bool(self.executable and shutil.which(self.executable))

    def version_command(self) -> list[str]:
        return [self.executable, "--version"]

    @abstractmethod
    def discover(self) -> list[UpdateItem]:
        raise NotImplementedError

    def discover_all(self) -> list[UpdateItem]:
        raise NotImplementedError(f"{self.label} does not expose installed-package inventory")

    @abstractmethod
    def build_update_command(self, item: UpdateItem) -> list[str]:
        raise NotImplementedError

    def build_uninstall_command(self, item: UpdateItem) -> list[str]:
        raise ValueError(f"{self.label} does not expose an exact uninstall route")

    def update(self, item: UpdateItem) -> CommandResult:
        if not valid_package_id(item.package_id):
            return immediate_command_error("unsafe package identifier")
        try:
            command = self.build_update_command(item)
        except (OSError, ValueError) as exc:
            return immediate_command_error(str(exc))
        return run_capture(command, timeout=7200)

    def uninstall(self, item: UpdateItem) -> CommandResult:
        try:
            command = self.build_uninstall_command(item)
        except (OSError, ValueError) as exc:
            return immediate_command_error(str(exc))
        return run_capture(command, timeout=7200)

    def succeeded(self, result: CommandResult) -> bool:
        code = normalized_exit_code(result.returncode)
        return (
            code in self.success_codes or code in self.already_current_codes
        ) and not result.exception

    def needs_reboot(self, result: CommandResult) -> bool:
        return not result.exception and normalized_exit_code(result.returncode) in self.reboot_codes

    def status_hint(self, result: CommandResult) -> str:
        if result.capture_truncated or not result.capture_complete:
            return "Output incomplete — verify before retrying"
        if result.exception:
            return ""
        code = normalized_exit_code(result.returncode)
        if code in self.not_applicable_codes:
            note = self.note_by_code.get(code, "the selected update is not applicable")
            return f"Not applicable • {note}"
        if code in self.canceled_codes:
            return "Canceled by package manager or installer"
        if code in self.already_current_codes:
            return "Already current"
        if code in self.reboot_codes:
            return "Updated • restart required"
        if not self.succeeded(result):
            note = self.note_by_code.get(code, "")
            return f"Failed • {note}" if note else ""
        return ""

    def outcome(self, result: CommandResult) -> str:
        code = normalized_exit_code(result.returncode)
        if not result.exception and code in self.not_applicable_codes:
            return "not-applicable"
        if not result.exception and code in self.canceled_codes:
            return "canceled"
        if not self.succeeded(result):
            return "failed"
        if code in self.already_current_codes:
            return "already-current"
        if code in self.reboot_codes:
            return "updated-restart-required"
        return "updated"

    def result_warnings(self, result: CommandResult) -> list[str]:
        return []


def inventory_only_item(
    *,
    provider: str,
    name: str,
    package_id: str,
    current: str,
    source: str,
    scope: str = "user",
    requires_admin: bool = False,
    instance: int = 0,
    guidance: str = "",
) -> UpdateItem:
    return UpdateItem(
        provider=provider,
        name=name or package_id,
        package_id=package_id,
        current=current or "?",
        available=current or "?",
        source=source,
        scope=scope,
        requires_admin=requires_admin,
        selected=False,
        status="Installed - no update shown",
        instance=instance,
        classification=CLASS_INVENTORY_ONLY,
        guidance=guidance
        or (
            "This row came from the All packages inventory view. It is "
            "read-only evidence, not an update candidate."
        ),
        applicability_prediction=PREDICTION_UNKNOWN,
        prediction_confidence="high",
        prediction_source="installed-inventory",
        prediction_reasons=(
            "All packages lists installed inventory without checking latest versions",
        ),
    )


def portable_record_date_evidence(
    record: PortableRecord,
) -> tuple[str, str, str, str, tuple[str, ...]]:
    if not record.approximate_date:
        return "", "", "", "", ()
    try:
        executable_stat = Path(record.executable).stat()
    except OSError:
        return "", "", "", "", ()
    if (
        executable_stat.st_mtime_ns != record.approximate_date_mtime_ns
        or executable_stat.st_size != record.approximate_date_size
    ):
        return "", "", "", "", ()
    return (
        record.approximate_date,
        record.approximate_timestamp,
        record.approximate_timestamp_precision,
        record.approximate_date_source,
        record.approximate_date_evidence,
    )


def portable_record_to_item(record: PortableRecord) -> UpdateItem:
    path_digest = hashlib.sha256(
        _portable_path_key(record.executable).encode("utf-8", errors="replace")
    ).hexdigest()[:16]
    package_id = f"portable.{record.app_key}.{path_digest}"
    removal = portable_removal_plan(
        app_key=record.app_key,
        executable=record.executable,
        scan_root=record.scan_root,
    )
    status_parts = ["Portable app"]
    if record.portable_format == "PortableApps.com":
        status_parts.append("verified PAF layout")
    elif record.detection_confidence == "high":
        status_parts.append("high-confidence local evidence")
    if record.catalog_available_version:
        release_source = "WinGet catalog" if record.catalog_package_id else "Release clue"
        status_parts.append(f"{release_source} {record.catalog_available_version}")
    elif record.catalog_checked_at:
        status_parts.append("catalog version unavailable")
    if removal is not None:
        status_parts.append(f"removable {removal.kind}")
    (
        installed_date,
        installed_timestamp,
        installed_timestamp_precision,
        installed_date_source,
        _date_evidence,
    ) = (
        portable_record_date_evidence(record)
    )
    return UpdateItem(
        provider=PORTABLE_PROVIDER_KEY,
        name=record.name,
        package_id=package_id,
        current=record.version,
        available=(
            record.catalog_available_version
            or ("Not found" if record.catalog_checked_at else "Not checked")
        ),
        source="folder-scan",
        scope="portable",
        requires_admin=False,
        selected=False,
        status=" · ".join(status_parts),
        classification=CLASS_INVENTORY_ONLY,
        guidance=(
            "Detected from a folder you chose. This release inventories portable apps and "
            "their local artwork, but does not yet attempt an in-place portable update."
        ),
        icon_source=record.icon_source,
        installed_for="portable folder",
        installed_technology="portable executable",
        installed_location=str(Path(record.executable).parent),
        installed_date=installed_date,
        installed_timestamp=installed_timestamp,
        installed_timestamp_precision=installed_timestamp_precision,
        installed_date_source=installed_date_source,
        installed_date_is_estimate=bool(installed_date),
        metadata_sources=("portable-folder-scan",),
        metadata_confidence="high",
        applicability_prediction=PREDICTION_UNKNOWN,
        prediction_confidence="high",
        prediction_source="portable-folder-scan",
        prediction_reasons=(
            f"Matched by {record.detected_by}",
            "No package-manager registration or generic update route was assumed",
        ),
        portable_executable=record.executable,
        portable_scan_root=record.scan_root,
        portable_detected_by=record.detected_by,
        portable_on_path=record.path_on_path,
        portable_app_key=record.app_key,
        portable_publisher=record.publisher,
        portable_original_filename=record.original_filename,
        portable_homepage=record.homepage,
        portable_detection_confidence=record.detection_confidence,
        portable_evidence_score=record.evidence_score,
        portable_evidence_reasons=record.evidence_reasons,
        portable_format=record.portable_format,
        portable_removal_kind=removal.kind if removal is not None else "",
        portable_removal_target=removal.target if removal is not None else "",
        portable_removal_reason=removal.reason if removal is not None else "",
        portable_catalog_package_id=record.catalog_package_id,
        portable_catalog_name=record.catalog_name,
        portable_catalog_homepage=record.catalog_homepage,
        portable_catalog_download_url=record.catalog_download_url,
        portable_catalog_match_basis=record.catalog_match_basis,
        portable_catalog_checked_at=record.catalog_checked_at,
        portable_catalog_error=record.catalog_error,
    )


def _portableapps_metadata_for_record(
    record: PortableRecord,
) -> PortablePafMetadata | None:
    """Find the declaring appinfo.ini for one cached PortableApps launcher."""

    if record.portable_format != "PortableApps.com":
        return None
    executable = Path(record.executable)
    scan_root = Path(record.scan_root)
    for parent in executable.parents:
        if not _portable_path_is_within(parent, scan_root):
            break
        metadata = read_portableapps_metadata(parent / "App" / "AppInfo" / "appinfo.ini")
        if (
            metadata is not None
            and _portable_path_key(metadata.executable)
            == _portable_path_key(record.executable)
        ):
            return metadata
        if _portable_path_key(parent) == _portable_path_key(scan_root):
            break
    return None


def refresh_portable_local_records(
    records: Sequence[PortableRecord],
) -> PortableLocalRefreshResult:
    """Re-read versions for known portable executables without rescanning their trees."""

    refreshed: list[PortableRecord] = []
    version_changes = 0
    homepage_changes = 0
    checked = 0
    for record in records:
        executable = Path(record.executable)
        if not executable.is_file():
            refreshed.append(record)
            continue
        checked += 1
        replacement = dataclasses.replace(
            record,
            path_on_path=executable_folder_on_path(executable),
        )
        paf = _portableapps_metadata_for_record(record)
        if paf is not None:
            replacement = dataclasses.replace(
                replacement,
                name=paf.name or record.name,
                version=paf.version or record.version,
                icon_source=paf.icon_source or record.icon_source,
                publisher=paf.publisher or record.publisher,
                homepage=paf.homepage or record.homepage,
            )
        else:
            metadata = windows_file_version_strings(executable)
            version = _portable_version(metadata, executable.name)
            replacement = dataclasses.replace(
                replacement,
                version=version if version != "Unknown" else record.version,
                publisher=(
                    str(metadata.get("CompanyName", "")).strip() or record.publisher
                ),
                original_filename=(
                    str(metadata.get("OriginalFilename", "")).strip()
                    or record.original_filename
                ),
            )
        if not replacement.homepage:
            _version_clue, nearby_urls, _source = _portable_nearby_release_clues(
                replacement
            )
            homepage = portable_homepage_from_nearby_docs(
                replacement,
                nearby_urls,
            )
            if homepage:
                replacement = dataclasses.replace(replacement, homepage=homepage)
        version_changes += int(replacement.version != record.version)
        homepage_changes += int(replacement.homepage != record.homepage)
        refreshed.append(replacement)
    return PortableLocalRefreshResult(
        tuple(refreshed),
        checked,
        version_changes,
        homepage_changes,
    )


def _portable_numeric_version(value: str) -> tuple[int, ...] | None:
    folded = value.strip().casefold()
    if not folded or folded in {"unknown", "not checked", "not found"}:
        return None
    if re.search(r"[a-uw-z]", folded):
        return None
    numbers = tuple(int(part) for part in re.findall(r"\d+", folded))
    if not numbers:
        return None
    trimmed = list(numbers)
    while len(trimmed) > 2 and trimmed[-1] == 0:
        trimmed.pop()
    return tuple(trimmed)


def portable_catalog_is_newer(record: PortableRecord) -> bool:
    installed = _portable_numeric_version(record.version)
    available = _portable_numeric_version(record.catalog_available_version)
    if installed is None or available is None:
        return False
    width = max(len(installed), len(available))
    return available + (0,) * (width - len(available)) > installed + (0,) * (
        width - len(installed)
    )


def _portable_release_version_from_text(text: str, installed: str) -> str:
    """Return a newer version only when release-oriented wording supports it."""

    installed_numeric = _portable_numeric_version(installed)
    if installed_numeric is None:
        return ""
    candidates: list[tuple[tuple[int, ...], str]] = []
    version_token = r"v?\d+(?:\.\d+){1,3}"
    release_patterns = (
        re.compile(
            rf"(?i)\b(?:latest|current|stable|new)\s+"
            rf"(?:release|version|build)\s*(?:is|[:=\-])?\s*"
            rf"(?P<version>{version_token})(?![A-Za-z0-9])"
        ),
        re.compile(
            rf"(?i)\b(?:release|version)\s*(?:is|[:=\-])?\s*"
            rf"(?P<version>{version_token})(?![A-Za-z0-9])"
        ),
    )
    for raw_line in re.split(r"[\r\n]+", text):
        line = re.sub(r"\s+", " ", raw_line).strip()
        for match in (
            match
            for pattern in release_patterns
            for match in pattern.finditer(line)
        ):
            candidate = match.group("version")
            numeric = _portable_numeric_version(candidate)
            if numeric is None:
                continue
            if (
                numeric[0] > 400
                and installed_numeric
                and installed_numeric[0] <= 400
            ):
                # Do not let date-shaped changelog text (for example 2026.07)
                # masquerade as a conventional application version.
                continue
            width = max(len(installed_numeric), len(numeric))
            if numeric + (0,) * (width - len(numeric)) > installed_numeric + (0,) * (
                width - len(installed_numeric)
            ):
                candidates.append((numeric, candidate.lstrip("vV")))
    return max(candidates, default=((), ""))[1]


def _portable_release_document_is_app_owned(
    record: PortableRecord,
    document: Path,
) -> bool:
    """Require a nearby release document to belong to the portable identity."""

    identities = {
        normalized_package_name(value)
        for value in (
            record.name,
            Path(record.executable).stem,
            Path(record.original_filename).stem,
        )
        if normalized_package_name(value)
    }
    if not identities:
        return False
    document_owner = normalized_package_name(document.parent.name)
    document_name = normalized_package_name(document.stem)
    for identity in identities:
        if len(identity) < 4:
            continue
        if document_owner == identity or document_name == identity:
            return True
        if (
            min(len(document_owner), len(identity)) >= 5
            and (document_owner in identity or identity in document_owner)
        ):
            return True
        if (
            min(len(document_name), len(identity)) >= 5
            and (document_name in identity or identity in document_name)
        ):
            return True
    return False


def _portable_nearby_release_clues(
    record: PortableRecord,
) -> tuple[str, tuple[str, ...], str]:
    """Inspect a few nearby human-authored release files without walking another tree."""

    executable = Path(record.executable)
    scan_root = Path(record.scan_root)
    documents: list[Path] = []
    directory = executable.parent
    for _depth in range(4):
        if not _portable_path_is_within(directory, scan_root):
            break
        try:
            documents.extend(
                candidate
                for candidate in directory.iterdir()
                if not _portable_path_is_reparse_point(candidate)
                and candidate.is_file()
                and _portable_release_document_is_app_owned(record, candidate)
                and re.match(
                    r"(?i)^(?:readme|changes?|changelog|history|release(?:notes)?|version)"
                    r"(?:[._ -].*)?$",
                    candidate.name,
                )
                and candidate.stat().st_size <= 512 * 1024
            )
        except OSError:
            pass
        if directory == scan_root or directory.parent == directory:
            break
        directory = directory.parent
    urls: list[str] = []
    best_version = ""
    best_source = ""
    for document in documents[:16]:
        try:
            text = document.read_text(encoding="utf-8-sig", errors="replace")
        except OSError:
            continue
        version = _portable_release_version_from_text(text, record.version)
        if version and (
            not best_version
            or (_portable_numeric_version(version) or ())
            > (_portable_numeric_version(best_version) or ())
        ):
            best_version = version
            best_source = str(document)
        for raw_url in re.findall(r"https://[^\s<>'\"`]+", text, flags=re.IGNORECASE):
            url = _portable_catalog_http_url(html.unescape(raw_url).rstrip(".,;:!?)]}"))
            if url and url not in urls:
                urls.append(url)
    return best_version, tuple(urls[:8]), best_source


def _portable_public_release_url(url: str) -> str:
    """Admit only ordinary public HTTPS pages for optional metadata reads."""

    candidate = _portable_catalog_http_url(url)
    if not candidate:
        return ""
    parsed = urllib.parse.urlparse(candidate)
    if parsed.scheme.casefold() != "https":
        return ""
    hostname = (parsed.hostname or "").casefold().rstrip(".")
    try:
        port = parsed.port
    except ValueError:
        return ""
    if (
        not hostname
        or hostname == "localhost"
        or hostname.endswith((".local", ".localhost", ".internal"))
        or "." not in hostname
        or port not in {None, 443}
    ):
        return ""
    with contextlib.suppress(ValueError):
        address = ipaddress.ip_address(hostname.strip("[]"))
        if not address.is_global:
            return ""
    return candidate


_NON_LAUNCH_EXECUTABLE_STEMS = {
    "install",
    "installer",
    "maintenance",
    "setup",
    "uninstall",
    "uninstaller",
    "update",
    "updater",
}


def launchable_executable(item: UpdateItem) -> Path | None:
    """Return a locally proven app executable without guessing inside folders."""

    raw_candidates: list[str] = []
    if item.provider == PORTABLE_PROVIDER_KEY and item.portable_executable:
        raw_candidates.append(item.portable_executable)
    if (
        item.icon_source
        and item.metadata_confidence == "proven"
        and "arp-uninstall" in item.metadata_sources
    ):
        raw_candidates.append(strip_display_icon_index(item.icon_source))

    for raw_candidate in raw_candidates:
        candidate = Path(os.path.expandvars(raw_candidate.strip().strip('"')))
        if candidate.suffix.casefold() != ".exe":
            continue
        folded_stem = candidate.stem.casefold()
        if folded_stem in _NON_LAUNCH_EXECUTABLE_STEMS or any(
            folded_stem.startswith(prefix)
            for prefix in ("unins", "uninst", "setup-", "update-", "updater-")
        ):
            continue
        try:
            if candidate.is_file():
                return candidate.resolve(strict=True)
        except OSError:
            continue
    return None


@dataclasses.dataclass(frozen=True, slots=True)
class AppRunRoute:
    kind: str
    target: Path | str


@dataclasses.dataclass(frozen=True, slots=True)
class WindowsShortcutDetails:
    target: str
    arguments: str = ""
    working_directory: str = ""


@functools.lru_cache(maxsize=512)
def _cached_launch_shortcut(
    path: Path, modified_ns: int, size: int,
) -> WindowsShortcutDetails | None:
    """Cache COM reads by the shortcut's file signature, not just its name."""
    return read_windows_shortcut(path)


_SHORTCUT_SCRIPT_HOSTS = frozenset(
    {
        "cmd",
        "cscript",
        "mshta",
        "powershell",
        "pwsh",
        "py",
        "python",
        "pythonw",
        "wscript",
    }
)
_SHORTCUT_SCRIPT_SUFFIXES = frozenset(
    {
        ".bat",
        ".cmd",
        ".hta",
        ".js",
        ".jse",
        ".ps1",
        ".psm1",
        ".py",
        ".pyw",
        ".vbe",
        ".vbs",
        ".wsf",
        ".wsh",
    }
)


def read_windows_shortcut(shortcut: Path) -> WindowsShortcutDetails | None:
    """Read one filesystem ``.lnk`` through the documented Shell COM object."""

    if os.name != "nt" or shortcut.suffix.casefold() != ".lnk" or not shortcut.is_file():
        return None
    clsid_shell_link = _guid_to_ctypes(
        uuid.UUID("{00021401-0000-0000-C000-000000000046}")
    )
    iid_shell_link = _guid_to_ctypes(
        uuid.UUID("{000214F9-0000-0000-C000-000000000046}")
    )
    iid_persist_file = _guid_to_ctypes(
        uuid.UUID("{0000010B-0000-0000-C000-000000000046}")
    )
    try:
        ole32 = ctypes.WinDLL("ole32", use_last_error=True)
        ole32.CoInitializeEx.argtypes = [ctypes.c_void_p, ctypes.c_uint32]
        ole32.CoInitializeEx.restype = ctypes.c_long
        ole32.CoCreateInstance.argtypes = [
            ctypes.c_void_p,
            ctypes.c_void_p,
            ctypes.c_uint32,
            ctypes.c_void_p,
            ctypes.POINTER(ctypes.c_void_p),
        ]
        ole32.CoCreateInstance.restype = ctypes.c_long
        ole32.CoUninitialize.argtypes = []
        ole32.CoUninitialize.restype = None
    except (AttributeError, OSError):
        return None

    initialized = int(ole32.CoInitializeEx(None, 0x2)) in {0, 1}
    shell_link = ctypes.c_void_p()
    persist_file = ctypes.c_void_p()
    try:
        result = int(
            ole32.CoCreateInstance(
                ctypes.byref(clsid_shell_link),
                None,
                0x1,  # CLSCTX_INPROC_SERVER
                ctypes.byref(iid_shell_link),
                ctypes.byref(shell_link),
            )
        )
        if result < 0 or not shell_link.value:
            return None
        shell_vtable = ctypes.cast(
            shell_link, ctypes.POINTER(ctypes.POINTER(ctypes.c_void_p))
        ).contents
        query_interface = ctypes.WINFUNCTYPE(
            ctypes.c_long,
            ctypes.c_void_p,
            ctypes.c_void_p,
            ctypes.POINTER(ctypes.c_void_p),
        )(shell_vtable[0])
        result = int(
            query_interface(
                shell_link,
                ctypes.byref(iid_persist_file),
                ctypes.byref(persist_file),
            )
        )
        if result < 0 or not persist_file.value:
            return None
        persist_vtable = ctypes.cast(
            persist_file, ctypes.POINTER(ctypes.POINTER(ctypes.c_void_p))
        ).contents
        load = ctypes.WINFUNCTYPE(
            ctypes.c_long, ctypes.c_void_p, ctypes.c_wchar_p, ctypes.c_uint32
        )(persist_vtable[5])
        if int(load(persist_file, str(shortcut), 0)) < 0:
            return None

        target_buffer = ctypes.create_unicode_buffer(32_768)
        arguments_buffer = ctypes.create_unicode_buffer(32_768)
        working_buffer = ctypes.create_unicode_buffer(32_768)
        get_path = ctypes.WINFUNCTYPE(
            ctypes.c_long,
            ctypes.c_void_p,
            ctypes.c_wchar_p,
            ctypes.c_int,
            ctypes.c_void_p,
            ctypes.c_uint32,
        )(shell_vtable[3])
        get_arguments = ctypes.WINFUNCTYPE(
            ctypes.c_long, ctypes.c_void_p, ctypes.c_wchar_p, ctypes.c_int
        )(shell_vtable[10])
        get_working_directory = ctypes.WINFUNCTYPE(
            ctypes.c_long, ctypes.c_void_p, ctypes.c_wchar_p, ctypes.c_int
        )(shell_vtable[8])
        get_path(shell_link, target_buffer, len(target_buffer), None, 0x4)
        get_arguments(shell_link, arguments_buffer, len(arguments_buffer))
        get_working_directory(shell_link, working_buffer, len(working_buffer))
        if not target_buffer.value.strip():
            return None
        return WindowsShortcutDetails(
            target=target_buffer.value,
            arguments=arguments_buffer.value,
            working_directory=working_buffer.value,
        )
    except (OSError, ValueError):
        return None
    finally:
        for interface in (persist_file, shell_link):
            if not interface.value:
                continue
            with contextlib.suppress(Exception):
                vtable = ctypes.cast(
                    interface, ctypes.POINTER(ctypes.POINTER(ctypes.c_void_p))
                ).contents
                release = ctypes.WINFUNCTYPE(ctypes.c_ulong, ctypes.c_void_p)(vtable[2])
                release(interface)
        if initialized:
            ole32.CoUninitialize()


def _windows_command_line_arguments(arguments: str) -> tuple[str, ...]:
    """Split saved shortcut arguments with Windows' own quoting rules."""

    if not arguments.strip():
        return ()
    if os.name != "nt":
        with contextlib.suppress(ValueError):
            return tuple(value.strip('"') for value in shlex.split(arguments, posix=False))
        return ()
    shell32 = ctypes.WinDLL("shell32", use_last_error=True)
    kernel32 = ctypes.WinDLL("kernel32", use_last_error=True)
    shell32.CommandLineToArgvW.argtypes = [ctypes.c_wchar_p, ctypes.POINTER(ctypes.c_int)]
    shell32.CommandLineToArgvW.restype = ctypes.POINTER(ctypes.c_wchar_p)
    kernel32.LocalFree.argtypes = [ctypes.c_void_p]
    kernel32.LocalFree.restype = ctypes.c_void_p
    count = ctypes.c_int()
    values = shell32.CommandLineToArgvW(f"shortcut-host.exe {arguments}", ctypes.byref(count))
    if not values:
        return ()
    try:
        return tuple(values[index] for index in range(1, count.value))
    finally:
        kernel32.LocalFree(values)


def _shortcut_local_path(raw_path: str, *bases: Path) -> Path | None:
    candidate = Path(os.path.expandvars(raw_path.strip().strip('"')))
    candidates = (candidate,) if candidate.is_absolute() else tuple(base / candidate for base in bases)
    for path in candidates:
        with contextlib.suppress(OSError):
            if path.exists():
                return path.resolve(strict=True)
    return None


def _shortcut_is_script_host(executable: Path) -> bool:
    stem = executable.stem.casefold()
    return stem in _SHORTCUT_SCRIPT_HOSTS or re.fullmatch(
        r"pythonw?(?:\d+(?:\.\d+)*)?", stem
    ) is not None


def _shortcut_hosted_target(
    executable: Path,
    details: WindowsShortcutDetails,
    *bases: Path,
) -> Path | None:
    """Return a saved local payload only for a recognized script host."""

    if not _shortcut_is_script_host(executable):
        return None
    accepted_suffixes = _SHORTCUT_SCRIPT_SUFFIXES
    if executable.stem.casefold() in {"cmd", "powershell", "pwsh"}:
        accepted_suffixes |= {".com", ".exe"}
    for argument in _windows_command_line_arguments(details.arguments):
        if Path(argument.strip().strip('"')).suffix.casefold() not in accepted_suffixes:
            continue
        candidate = _shortcut_local_path(argument, *bases)
        if candidate is not None and candidate.is_file():
            return candidate
    return None


def shortcut_terminal_target(
    shortcut: Path,
    *,
    read_shortcut: Callable[[Path], WindowsShortcutDetails | None] = read_windows_shortcut,
    max_hops: int = 8,
) -> Path | None:
    """Follow a bounded local ``.lnk`` chain to its real executable or script."""

    with contextlib.suppress(OSError):
        current = shortcut.resolve(strict=True)
        visited: set[str] = set()
        for _hop in range(max(1, min(max_hops, 16))):
            key = os.path.normcase(os.path.abspath(current))
            if key in visited or current.suffix.casefold() != ".lnk":
                return None
            visited.add(key)
            details = read_shortcut(current)
            if details is None:
                return None
            working_directory = _shortcut_local_path(
                details.working_directory, current.parent
            ) if details.working_directory.strip() else None
            bases = tuple(
                dict.fromkeys(
                    base for base in (working_directory, current.parent) if base is not None
                )
            )
            target = _shortcut_local_path(details.target, *bases)
            if target is None:
                return None
            if target.suffix.casefold() == ".lnk":
                current = target
                continue
            if _shortcut_is_script_host(target):
                return _shortcut_hosted_target(target, details, *bases)
            return target
    return None


def windows_package_launch_ids(record: Mapping[str, Any]) -> tuple[str, ...]:
    """Bind visible manifest applications to the enumerated package family."""
    full_name = str(record.get("full_name", ""))
    parts = full_name.rsplit("_", 4)
    family = str(record.get("family", ""))
    if len(parts) != 5 or family != f"{parts[0]}_{parts[-1]}":
        return ()
    ids = record.get("launch_ids", [])
    if not isinstance(ids, list) or len(ids) > 256:
        return ()
    return tuple(dict.fromkeys(
        f"{family}!{app_id}" for app_id in ids
        if isinstance(app_id, str)
        and re.fullmatch(r"[A-Za-z0-9.-]{1,150}", app_id)
        and re.fullmatch(r"[A-Za-z0-9.-]+_[A-Za-z0-9]{13}", family)
    ))


def registered_launch_package(
    provider: str, package_id: str, current: str = "",
) -> tuple[str, Path] | None:
    """Join a known catalog identity or exact MSIX ID to this account's registration."""
    if provider not in {"winget", MICROSOFT_STORE_PROVIDER_KEY}:
        return None
    full_id = package_id[5:] if package_id.casefold().startswith("msix\\") else ""
    family = KNOWN_WINGET_PACKAGE_FAMILIES.get(package_id.casefold(), "") if provider == "winget" else ""
    if not full_id and not family:
        return None
    matches = []
    for full_name, _display, root in _installed_appx_repository_entries():
        parts = full_name.rsplit("_", 4)
        if len(parts) != 5:
            continue
        if full_id:
            matched = full_id.casefold() == full_name.casefold()
        else:
            matched = (
                f"{parts[0]}_{parts[-1]}".casefold() == family.casefold()
                and (not current or parts[1].casefold() == current.casefold())
            )
        if matched:
            matches.append((full_name, root))
    return matches[0] if len(matches) == 1 else None


@functools.lru_cache(maxsize=128)
def _registered_manifest_launch_ids(
    full_name: str, manifest: Path, modified_ns: int, size: int,
) -> tuple[str, ...]:
    """Read a bounded manifest once per file revision; retain only visible apps."""
    if not 0 < size <= 4 * 1024 * 1024:
        return ()
    try:
        with manifest.open("rb") as stream:
            payload = stream.read(size + 1)
        if len(payload) != size:
            return ()
        root = ET.fromstring(payload)
    except (OSError, ET.ParseError):
        return ()
    parts = full_name.rsplit("_", 4)
    identity = next((node for node in root if _xml_local_name(node.tag) == "Identity"), None)
    if len(parts) != 5 or identity is None or (
        identity.get("Name", "").casefold() != parts[0].casefold()
        or identity.get("Version", "") != parts[1]
    ):
        return ()
    app_ids = []
    for group in root:
        if _xml_local_name(group.tag) != "Applications":
            continue
        for app in group:
            if _xml_local_name(app.tag) != "Application":
                continue
            visual = next((node for node in app if _xml_local_name(node.tag) == "VisualElements"), None)
            if visual is not None and not any(
                _xml_local_name(key) == "AppListEntry" and value.casefold() == "none"
                for key, value in visual.attrib.items()
            ):
                app_ids.append(app.get("Id", ""))
    return windows_package_launch_ids({
        "full_name": full_name, "family": f"{parts[0]}_{parts[-1]}", "launch_ids": app_ids,
    })


@functools.lru_cache(maxsize=256)
def _launch_folder_entries(folder: Path, modified_ns: int) -> tuple[Path, ...]:
    """Bounded, nonrecursive discovery in an already verified install folder."""
    with os.scandir(folder) as entries:
        paths = []
        for index, entry in enumerate(entries):
            if index >= 128:
                return ()
            if entry.name.casefold().endswith(".exe") and entry.is_file(follow_symlinks=False):
                paths.append(Path(entry.path))
        return tuple(paths)


@functools.lru_cache(maxsize=512)
def _launch_executable_identity(path: Path, modified_ns: int, size: int) -> tuple[str, ...]:
    if portable_pe_subsystem(path) not in {2, 3}:
        return ()
    # Do not offer an ARM binary on x64 just because its product strings match.
    with path.open("rb") as stream:
        stream.seek(0x3C)
        offset_bytes = stream.read(4)
        if len(offset_bytes) != 4:
            return ()
        offset = struct.unpack("<I", offset_bytes)[0]
        if offset > size - 6:
            return ()
        stream.seek(offset + 4)
        machine_bytes = stream.read(2)
    if len(machine_bytes) != 2:
        return ()
    machine = struct.unpack("<H", machine_bytes)[0]
    if machine not in ({0x14C, 0x8664, 0xAA64} if platform.machine().lower() == "arm64" else {0x14C, 0x8664}):
        return ()
    info = windows_file_version_strings(path)
    return tuple(_icon_match_text(info.get(key, "")) for key in ("ProductName", "FileDescription", "OriginalFilename"))


def installed_folder_launch_paths(item: UpdateItem) -> tuple[Path, ...]:
    """Never promote an arbitrary executable merely because it shares a folder."""
    if (
        not item.installed_location or item.metadata_confidence != "proven"
        or "arp-uninstall" not in item.metadata_sources
    ):
        return ()
    folder = Path(os.path.expandvars(item.installed_location.strip().strip('"')))
    if not folder.is_absolute() or str(folder).startswith("\\\\"):
        return ()
    matches = []
    names = {_icon_match_text(item.name), _icon_match_text(item.package_id.rsplit(".", 1)[-1])}
    names.discard("")
    try:
        if _portable_path_is_reparse_point(folder):
            return ()
        for path in _launch_folder_entries(folder, folder.stat().st_mtime_ns):
            stem = path.stem.casefold()
            if any(word in stem for word in _NON_LAUNCH_EXECUTABLE_STEMS) or stem.startswith(("unins", "uninst")):
                continue
            if _portable_path_is_reparse_point(path):
                continue
            stat = path.stat()
            identities = _launch_executable_identity(path, stat.st_mtime_ns, stat.st_size)
            stem_identity = _icon_match_text(re.sub(r"(?:64a|64|32)$", "", path.stem, flags=re.I))
            if identities and (
                stem_identity in names
                or (
                    identities[0] in names
                    and identities[1].endswith(identities[0])
                    and identities[2] == stem_identity + "exe"
                )
                or identities[1] in names
            ):
                matches.append(path.resolve(strict=True))
    except OSError:
        return ()
    return tuple(matches)


def app_run_routes(item: UpdateItem) -> tuple[AppRunRoute, ...]:
    """Prefer registered/saved activation routes; retain genuinely different choices."""

    executable = launchable_executable(item)
    if item.provider == PORTABLE_PROVIDER_KEY and executable is not None:
        return (AppRunRoute("executable", executable),)
    if item.scope == "user" and {"windows-packagemanager", "appx-package-repository"}.intersection(item.metadata_sources):
        app_ids = tuple(dict.fromkeys(
            app_id for app_id in item.launch_app_ids
            if re.fullmatch(r"[A-Za-z0-9.-]+_[A-Za-z0-9]{13}![A-Za-z0-9.-]{1,150}", app_id)
        ))
        if app_ids:
            return tuple(AppRunRoute("app-id", app_id) for app_id in app_ids)
    if item.scope == "user" and (
        item.package_id.casefold().startswith("msix\\")
        or item.installed_technology in {"", "unknown", "msix"}
    ):
        registered = registered_launch_package(item.provider, item.package_id, item.current)
        if registered is not None:
            full_name, root = registered
            manifest = root / "AppxManifest.xml"
            with contextlib.suppress(OSError):
                stat = manifest.stat()
                app_ids = _registered_manifest_launch_ids(full_name, manifest, stat.st_mtime_ns, stat.st_size)
                if app_ids:
                    return tuple(AppRunRoute("app-id", app_id) for app_id in app_ids)
    shortcuts = []
    launch_name = re.sub(
        rf"\s+(?:version\s+)?{re.escape(item.current)}$", "", item.name, flags=re.I,
    ) if item.current else item.name
    for shortcut in start_menu_shortcut_launch_paths(item.package_id, launch_name):
        with contextlib.suppress(OSError):
            if shortcut.is_file():
                shortcuts.append(AppRunRoute("shortcut", shortcut.resolve(strict=True)))
    if shortcuts:
        return tuple(shortcuts)
    if executable is not None:
        return (AppRunRoute("executable", executable),)
    return tuple(AppRunRoute("executable", path) for path in installed_folder_launch_paths(item))


def app_run_route(item: UpdateItem) -> AppRunRoute | None:
    routes = app_run_routes(item)
    return routes[0] if len(routes) == 1 else None


def run_allowed_during_activity(busy: bool, busy_kind: str) -> bool:
    return not busy or busy_kind == "scan"


def activate_app_route(route: AppRunRoute) -> None:
    """Launch in the current account; keep console apps and their output visible."""
    if route.kind == "app-id":
        if not re.fullmatch(r"[A-Za-z0-9.-]+_[A-Za-z0-9]{13}![A-Za-z0-9.-]{1,150}", str(route.target)):
            raise OSError("Invalid Windows application ID")
        os.startfile(f"shell:AppsFolder\\{route.target}")  # type: ignore[attr-defined]
    elif route.kind == "shortcut":
        os.startfile(route.target)  # type: ignore[attr-defined]
    elif route.kind == "executable" and isinstance(route.target, Path):
        if portable_pe_subsystem(route.target) == 3:
            # cmd /k preserves an interactive prompt after a short-lived CLI exits.
            # Percent expansion is cmd syntax even inside quotes: do not feed it paths.
            if any(char in str(route.target) for char in '%!\r\n'):
                raise OSError("This console path cannot safely be passed to a terminal")
            command_processor = str(Path(os.environ.get("SystemRoot", r"C:\Windows")) / "System32" / "cmd.exe")
            subprocess.Popen(
                f'"{command_processor}" /d /v:off /k ""{route.target}""',
                cwd=str(route.target.parent), close_fds=True,
                creationflags=subprocess.CREATE_NEW_CONSOLE,
            )
        else:
            os.startfile(route.target, cwd=str(route.target.parent))  # type: ignore[attr-defined]
    else:
        raise OSError("Unsupported application launch route")


def app_containing_target(
    item: UpdateItem,
    route: AppRunRoute | None = None,
    *,
    read_shortcut: Callable[[Path], WindowsShortcutDetails | None] = read_windows_shortcut,
) -> Path | None:
    """Return the real local app/script target used only for folder navigation."""

    route = route or app_run_route(item)
    if route is not None and route.kind == "shortcut" and route.target.suffix.casefold() == ".lnk":
        terminal_target = shortcut_terminal_target(route.target, read_shortcut=read_shortcut)
        if terminal_target is not None:
            return terminal_target

    executable = launchable_executable(item)
    if executable is not None:
        return executable
    installed_location = Path(os.path.expandvars(item.installed_location.strip().strip('"')))
    if item.installed_location.strip():
        with contextlib.suppress(OSError):
            if installed_location.is_dir():
                return installed_location.resolve(strict=True)
    if route is not None and route.kind == "executable":
        with contextlib.suppress(OSError):
            if route.target.is_file():
                return route.target.resolve(strict=True)
    return None


def app_containing_folder(item: UpdateItem, route: AppRunRoute | None = None) -> Path | None:
    """Return the parent folder for the locally verified app/navigation target."""

    target = app_containing_target(item, route)
    if target is None:
        return None
    return target if target.is_dir() else target.parent


def app_shortcut_path(route: AppRunRoute | None) -> Path | None:
    """Return the saved launch file so its own Start Menu folder can be opened."""

    if route is None or route.kind != "shortcut":
        return None
    with contextlib.suppress(OSError):
        if route.target.suffix.casefold() in {".lnk", ".url"} and route.target.is_file():
            return route.target.resolve(strict=True)
    return None


def app_local_path_details(
    item: UpdateItem,
    route: AppRunRoute | None = None,
    *,
    read_shortcut: Callable[[Path], WindowsShortcutDetails | None] = read_windows_shortcut,
) -> tuple[tuple[str, str], ...]:
    """Describe only locally proven launch/navigation paths for Package Details."""

    route = route or app_run_route(item)
    if route is None:
        return ()
    fields: list[tuple[str, str]] = [
        (
            {"shortcut": "Launch shortcut", "app-id": "Windows application ID"}.get(
                route.kind, "Launch executable"
            ),
            str(route.target),
        )
    ]
    resolved_target = route.target if route.kind == "executable" else None
    if route.kind == "shortcut" and route.target.suffix.casefold() == ".lnk":
        resolved_target = shortcut_terminal_target(route.target, read_shortcut=read_shortcut)
    if resolved_target is not None and resolved_target != route.target:
        fields.append(("Resolved local target", str(resolved_target)))
    navigation_target = resolved_target or app_containing_target(
        item,
        route,
        read_shortcut=read_shortcut,
    )
    if navigation_target is not None:
        containing_folder = (
            navigation_target if navigation_target.is_dir() else navigation_target.parent
        )
        installed_location = item.installed_location.strip().strip('"')
        installed_folder: Path | None = None
        if installed_location:
            with contextlib.suppress(OSError):
                candidate = Path(os.path.expandvars(installed_location)).resolve(strict=True)
                installed_folder = candidate if candidate.is_dir() else candidate.parent
        if installed_folder is None or containing_folder != installed_folder:
            fields.append(("Containing folder", str(containing_folder)))
    return tuple(fields)


def reveal_in_windows_explorer(target: Path) -> None:
    """Open a folder or select one file without Explorer's fragile command parser."""

    resolved = target.resolve(strict=True)
    if resolved.is_dir():
        os.startfile(resolved)  # type: ignore[attr-defined]
        return
    if os.name != "nt":
        raise OSError("Windows Explorer selection is available only on Windows")

    ole32 = ctypes.WinDLL("ole32", use_last_error=True)
    shell32 = ctypes.WinDLL("shell32", use_last_error=True)
    ole32.CoInitializeEx.argtypes = [ctypes.c_void_p, ctypes.c_uint32]
    ole32.CoInitializeEx.restype = ctypes.c_long
    ole32.CoUninitialize.argtypes = []
    ole32.CoUninitialize.restype = None
    shell32.ILCreateFromPathW.argtypes = [ctypes.c_wchar_p]
    shell32.ILCreateFromPathW.restype = ctypes.c_void_p
    shell32.SHOpenFolderAndSelectItems.argtypes = [
        ctypes.c_void_p,
        ctypes.c_uint,
        ctypes.c_void_p,
        ctypes.c_uint32,
    ]
    shell32.SHOpenFolderAndSelectItems.restype = ctypes.c_long
    shell32.ILFree.argtypes = [ctypes.c_void_p]
    shell32.ILFree.restype = None

    initialized = int(ole32.CoInitializeEx(None, 0x2)) in {0, 1}
    item_id_list = shell32.ILCreateFromPathW(str(resolved))
    try:
        if item_id_list and int(
            shell32.SHOpenFolderAndSelectItems(item_id_list, 0, None, 0)
        ) >= 0:
            return
    finally:
        if item_id_list:
            shell32.ILFree(item_id_list)
        if initialized:
            ole32.CoUninitialize()

    # The folder is still the truthful destination if Shell selection is
    # unavailable for an unusual namespace/item. Never fall back to Documents.
    os.startfile(resolved.parent)  # type: ignore[attr-defined]


def _portable_url_origin(url: str) -> tuple[str, str, int] | None:
    candidate = _portable_public_release_url(url)
    if not candidate:
        return None
    parsed = urllib.parse.urlparse(candidate)
    return (
        parsed.scheme.casefold(),
        (parsed.hostname or "").casefold().rstrip("."),
        parsed.port or 443,
    )


def _portable_urls_share_origin(left: str, right: str) -> bool:
    return bool(
        (left_origin := _portable_url_origin(left))
        and left_origin == _portable_url_origin(right)
    )


def _portable_urls_share_declared_host(left: str, right: str) -> bool:
    """Allow only an exact declared host, ignoring a conventional ``www`` prefix."""

    left_origin = _portable_url_origin(left)
    right_origin = _portable_url_origin(right)
    if not left_origin or not right_origin:
        return False
    left_scheme, left_host, left_port = left_origin
    right_scheme, right_host, right_port = right_origin
    return (
        left_scheme == right_scheme
        and left_port == right_port
        and left_host.removeprefix("www.") == right_host.removeprefix("www.")
    )


def _portable_github_repo_matches_record(url: str, record: PortableRecord) -> bool:
    candidate = _portable_public_release_url(url)
    if not candidate:
        return False
    parsed = urllib.parse.urlparse(candidate)
    parts = [urllib.parse.unquote(part) for part in parsed.path.split("/") if part]
    if (parsed.hostname or "").casefold() != "github.com" or len(parts) < 2:
        return False
    repository = normalized_package_name(parts[1].removesuffix(".git"))
    identities = {
        normalized_package_name(record.name),
        normalized_package_name(Path(record.executable).stem),
        normalized_package_name(Path(record.original_filename).stem),
    }
    return any(
        len(identity) >= 4
        and (
            repository == identity
            or repository in identity
            or identity in repository
        )
        for identity in identities
        if identity
    )


def portable_homepage_from_nearby_docs(
    record: PortableRecord,
    urls: Sequence[str],
) -> str:
    """Select only a project-looking HTTPS homepage from nearby documentation."""

    identities = {
        normalized_package_name(record.name),
        normalized_package_name(Path(record.executable).stem),
        normalized_package_name(Path(record.original_filename).stem),
    }
    for raw_url in urls:
        url = _portable_public_release_url(raw_url)
        if not url:
            continue
        if _portable_github_repo_matches_record(url, record):
            return url
        hostname = (urllib.parse.urlparse(url).hostname or "").casefold()
        host_identity = normalized_package_name(hostname.removeprefix("www."))
        if any(
            len(identity) >= 5 and identity in host_identity
            for identity in identities
            if identity
        ):
            return url
    return ""


class _PortableSameOriginRedirectHandler(urllib.request.HTTPRedirectHandler):
    """Refuse advisory-fetch redirects that leave the validated HTTPS origin."""

    def redirect_request(
        self,
        req: urllib.request.Request,
        fp: Any,
        code: int,
        msg: str,
        headers: Any,
        newurl: str,
    ) -> urllib.request.Request | None:
        target = urllib.parse.urljoin(req.full_url, newurl)
        if not _portable_urls_share_origin(req.full_url, target):
            raise urllib.error.HTTPError(
                req.full_url,
                code,
                "portable advisory redirect left the validated origin",
                headers,
                fp,
            )
        return super().redirect_request(req, fp, code, msg, headers, target)


def _portable_fetch_official_release_clue(url: str, installed: str) -> tuple[str, str, str]:
    """Read one bounded official page or GitHub release API as advisory evidence."""

    candidate = _portable_public_release_url(url)
    if not candidate:
        return "", "", ""
    parsed = urllib.parse.urlparse(candidate)
    github_match = re.match(
        r"^/([^/]+)/([^/#?]+)",
        parsed.path,
    ) if parsed.hostname and parsed.hostname.casefold() == "github.com" else None
    request_url = candidate
    basis = "official project page"
    if github_match:
        owner, repository = github_match.groups()
        repository = repository.removesuffix(".git")
        request_url = (
            "https://api.github.com/repos/"
            f"{urllib.parse.quote(owner, safe='')}/{urllib.parse.quote(repository, safe='')}"
            "/releases/latest"
        )
        basis = "official GitHub latest release"
    request = urllib.request.Request(
        request_url,
        headers={
            "User-Agent": f"{APP_NAME}/{APP_VERSION}",
            "Accept": "application/vnd.github+json, text/html;q=0.9, text/plain;q=0.8",
        },
    )
    try:
        opener = urllib.request.build_opener(_PortableSameOriginRedirectHandler())
        with opener.open(request, timeout=12) as response:
            if not _portable_urls_share_origin(request_url, response.geturl()):
                return "", "", ""
            payload = response.read(1_000_001)
            content_type = response.headers.get_content_type()
    except (OSError, urllib.error.URLError, ValueError):
        return "", "", ""
    if len(payload) > 1_000_000:
        return "", "", ""
    text = payload.decode("utf-8", errors="replace")
    release_url = candidate
    if github_match and content_type == "application/json":
        try:
            decoded = json.loads(text)
        except json.JSONDecodeError:
            return "", "", ""
        if not isinstance(decoded, dict):
            return "", "", ""
        tag = str(decoded.get("tag_name", "")).strip()
        version = _portable_release_version_from_text(f"Latest release {tag}", installed)
        returned_url = _portable_public_release_url(str(decoded.get("html_url", "")))
        release_url = (
            returned_url
            if returned_url and _portable_urls_share_origin(candidate, returned_url)
            else candidate
        )
        return version, release_url, basis
    plain_text = re.sub(r"<[^>]{0,500}>", " ", html.unescape(text))
    return _portable_release_version_from_text(plain_text, installed), release_url, basis


def refresh_portable_release_clue(record: PortableRecord) -> PortableRecord:
    """Attach a read-only local/official version clue when WinGet has no safe match."""

    local_version, discovered_urls, local_source = _portable_nearby_release_clues(record)
    declared_homepage = _portable_public_release_url(record.homepage)
    fetch_urls: list[str] = [declared_homepage] if declared_homepage else []
    for value in discovered_urls:
        url = _portable_public_release_url(value)
        if not url:
            continue
        if (
            declared_homepage
            and _portable_urls_share_declared_host(url, declared_homepage)
        ) or _portable_github_repo_matches_record(url, record):
            fetch_urls.append(url)
    urls = tuple(dict.fromkeys(fetch_urls))
    if local_version:
        return dataclasses.replace(
            record,
            catalog_available_version=local_version,
            catalog_homepage=urls[0] if urls else record.homepage,
            catalog_match_basis=(
                "newer version stated in identity-matched nearby release documentation"
                + (f": {local_source}" if local_source else "")
            ),
        )
    for url in urls[:3]:
        version, release_url, basis = _portable_fetch_official_release_clue(
            url,
            record.version,
        )
        if version:
            return dataclasses.replace(
                record,
                catalog_available_version=version,
                catalog_homepage=release_url or url,
                catalog_match_basis=basis,
            )
    if urls:
        return dataclasses.replace(
            record,
            catalog_homepage=urls[0],
            catalog_match_basis=(
                record.catalog_match_basis
                or "official project page discovered in nearby documentation"
            ),
        )
    return record


def portable_record_to_update_item(record: PortableRecord) -> UpdateItem | None:
    if not portable_catalog_is_newer(record):
        return None
    item = portable_record_to_item(record)
    item.classification = CLASS_MANUAL_REVIEW
    item.applicability_prediction = PREDICTION_NOT_APPLICABLE
    item.prediction_confidence = "high"
    item.prediction_source = "portable-catalog-advisory"
    item.prediction_reasons = (
        "a newer catalog release was found for this locally portable executable",
        "installing the provider package could replace the chosen portable layout "
        "with a registered installation",
    )
    item.status = "Manual portable update available"
    item.guidance = (
        "A newer release appears in the trusted catalog, but WinDevPilot will not "
        "install it over this portable copy. Download and replace the portable files "
        "manually to preserve the portable layout."
    )
    item.guidance_url = record.catalog_homepage or record.catalog_download_url
    item.selected = False
    return item


def portable_manual_update_page(item: UpdateItem) -> str:
    """Return only a vetted project page for a manual portable update action."""

    if item.provider != PORTABLE_PROVIDER_KEY:
        return ""
    return _portable_public_release_url(item.portable_catalog_homepage)


def refresh_portable_removal_fields(item: UpdateItem) -> PortableRemovalPlan | None:
    if item.provider != PORTABLE_PROVIDER_KEY:
        return None
    plan = portable_removal_plan(
        app_key=item.portable_app_key,
        executable=item.portable_executable,
        scan_root=item.portable_scan_root,
    )
    item.portable_removal_kind = plan.kind if plan is not None else ""
    item.portable_removal_target = plan.target if plan is not None else ""
    item.portable_removal_reason = plan.reason if plan is not None else ""
    item.status = (
        " · ".join(
            [
                "Portable app",
                *(
                    ["verified PAF layout"]
                    if item.portable_format == "PortableApps.com"
                    else (
                        ["high-confidence local evidence"]
                        if item.portable_detection_confidence == "high"
                        else []
                    )
                ),
                *(
                    [
                        (
                            "WinGet catalog"
                            if item.portable_catalog_package_id
                            else "Release clue"
                        )
                        + f" {item.available}"
                    ]
                    if item.available not in {"", "Not checked", "Not found"}
                    else (
                        ["catalog version unavailable"]
                        if item.portable_catalog_checked_at
                        else []
                    )
                ),
                *([f"removable {plan.kind}"] if plan is not None else []),
            ]
        )
    )
    return plan


def remove_portable_item(item: UpdateItem) -> CommandResult:
    """Delete only a route re-proven from the live filesystem immediately beforehand."""

    started_at = utc_now_iso()
    started_clock = time.perf_counter()
    plan = portable_removal_plan(
        app_key=item.portable_app_key,
        executable=item.portable_executable,
        scan_root=item.portable_scan_root,
    )
    requested = [
        APP_NAME,
        f"delete-portable-{item.portable_removal_kind or 'unproven'}",
        item.portable_removal_target,
    ]
    if (
        plan is None
        or plan.kind != item.portable_removal_kind
        or _portable_path_key(plan.target) != _portable_path_key(item.portable_removal_target)
    ):
        return immediate_command_error(
            "portable removal was refused because the filesystem no longer matches "
            "the confirmed deletion plan",
            requested_command=requested,
        )
    target = Path(plan.target)

    def clear_readonly_and_retry(
        function: Callable[[str], Any],
        path: str,
        error: BaseException,
    ) -> None:
        if not isinstance(error, PermissionError):
            raise error
        os.chmod(path, stat.S_IWRITE)
        function(path)

    try:
        if plan.kind == "file":
            try:
                target.unlink()
            except PermissionError:
                os.chmod(target, stat.S_IWRITE)
                target.unlink()
            output = f"Deleted the exact portable executable: {target}"
        elif plan.kind == "folder":
            # `portable_removal_plan` resolved and recursively inspected this exact
            # absolute folder, bounded it beneath the user-selected scan root, and
            # rejected reparse points immediately before this native Python removal.
            shutil.rmtree(target, onexc=clear_readonly_and_retry)
            output = f"Deleted the portable application folder: {target}"
        else:
            raise ValueError(f"unknown portable removal kind: {plan.kind}")
        return CommandResult(
            returncode=0,
            output=output,
            command=requested,
            requested_command=requested,
            started_at=started_at,
            finished_at=utc_now_iso(),
            duration_seconds=round(time.perf_counter() - started_clock, 3),
            process_id=os.getpid(),
        )
    except (OSError, ValueError) as exc:
        return CommandResult(
            returncode=1,
            output="",
            command=requested,
            exception=f"{type(exc).__name__}: {exc}",
            requested_command=requested,
            started_at=started_at,
            finished_at=utc_now_iso(),
            duration_seconds=round(time.perf_counter() - started_clock, 3),
            process_id=os.getpid(),
        )


def classify_winget_scopes(
    package_id: str,
    version: str,
    machine_pairs: set[tuple[str, str]],
    machine_ids: set[str],
    user_pairs: set[tuple[str, str]],
    user_ids: set[str],
) -> tuple[str, ...]:
    """Return only scopes supported by inventory evidence; never guess user scope."""
    folded_id = package_id.casefold()
    pair = (folded_id, version.casefold())
    in_machine = pair in machine_pairs
    in_user = pair in user_pairs
    if in_machine and in_user:
        return ("user", "machine")
    if in_machine:
        return ("machine",)
    if in_user:
        return ("user",)
    id_in_machine = folded_id in machine_ids
    id_in_user = folded_id in user_ids
    if id_in_machine and not id_in_user:
        return ("machine",)
    if id_in_user and not id_in_machine:
        return ("user",)
    return ()


class WingetProvider(Provider):
    key = "winget"
    label = "WinGet"
    executable = "winget"
    elevation_allowed = True
    success_codes = WINGET_SUCCESS_CODES
    already_current_codes = WINGET_ALREADY_CURRENT_CODES
    not_applicable_codes = WINGET_NOT_APPLICABLE_CODES
    canceled_codes = WINGET_CANCELED_CODES
    reboot_codes = WINGET_REBOOT_CODES
    note_by_code = WINGET_NOTE_BY_CODE

    def __init__(self) -> None:
        super().__init__()
        self._manifest_cache: dict[tuple[str, str, str], tuple[float, WingetManifestMetadata]] = {}
        self._scan_installed_inventory: WindowsInstalledInventory | None = None
        self._pin_types_by_id: dict[str, str] = {}
        self._pin_state_untrusted = False
        self.recent_inventory_hits = 0

    def _read_package_rows(
        self,
        command: Sequence[str],
        headers: Sequence[str],
        *,
        updates: bool,
        timeout: int,
    ) -> tuple[CommandResult, list[dict[str, str]], str, bool]:
        """Return rows plus explicit proof when a structured result is empty."""

        structured_error = ""
        structured_arguments = winget_structured_output_arguments(str(command[1]))
        if structured_arguments:
            structured_result = run_capture(
                [*command, *structured_arguments],
                timeout=timeout,
            )
            if structured_result.returncode in {0, 1}:
                try:
                    structured_rows = parse_winget_structured_rows(
                        structured_result.output,
                        updates=updates,
                    )
                    return (
                        structured_result,
                        structured_rows,
                        "",
                        not structured_rows,
                    )
                except (TypeError, ValueError, json.JSONDecodeError) as exc:
                    structured_error = f"structured output was rejected: {exc}"
            else:
                structured_error = (
                    structured_result.exception
                    or structured_result.output.strip()
                    or f"structured output exited {structured_result.returncode}"
                )[-500:]
        result = run_capture(command, timeout=timeout)
        try:
            rows = parse_winget_table_consensus(
                result.output,
                headers,
                require_available=updates,
            )
        except ValueError as exc:
            detail = f"table consensus rejected output: {exc}"
            if structured_error:
                detail = f"{structured_error}; {detail}"
            return result, [], detail, False
        return result, rows, "", False

    def _discover_pin_types(self) -> dict[str, str]:
        """Read WinGet pins without exposing new choices or changing pin state."""

        self._pin_state_untrusted = False
        result = run_capture(
            ["winget", "pin", "list", "--disable-interactivity"],
            timeout=60,
        )
        if result.returncode not in {0, 1}:
            detail = result.exception or result.output.strip() or "no diagnostic output"
            self.warnings.append(f"WinGet pin state was unavailable: {detail[-500:]}")
            self._pin_state_untrusted = True
            return {}
        if "no pins configured" in clean_output(result.output).casefold():
            return {}
        rows: list[dict[str, str]] = []
        for headers in (
            ("Name", "Id", "Version", "Type", "Source"),
            ("Name", "Id", "Version", "Type"),
            ("Name", "Id", "Type"),
        ):
            try:
                rows = parse_winget_table_consensus(
                    result.output,
                    headers,
                    require_version="Version" in headers,
                )
            except ValueError as exc:
                self.warnings.append(f"WinGet pin table was not trusted: {exc}")
                self._pin_state_untrusted = True
                return {}
            if rows:
                break
        if not rows:
            if output_looks_like_package_table(result.output):
                warning = "WinGet pin table layout was not recognized"
            else:
                warning = "WinGet pin state returned no trustworthy result"
            self.warnings.append(f"{warning}; update candidates require review")
            self._pin_state_untrusted = True
            return {}
        priority = {"gating": 1, "pinning": 2, "blocking": 3}
        pins: dict[str, str] = {}
        for row in rows:
            package_id = row.get("Id", "").strip()
            pin_type = row.get("Type", "").strip().casefold()
            if not valid_package_id(package_id) or pin_type not in priority:
                if not self._pin_state_untrusted:
                    self.warnings.append(
                        "WinGet pin table contained an untrusted identity or pin type; "
                        "update candidates require review"
                    )
                self._pin_state_untrusted = True
                continue
            folded_id = package_id.casefold()
            current = pins.get(folded_id, "")
            if priority[pin_type] > priority.get(current, 0):
                pins[folded_id] = pin_type
        return pins

    def _pin_leaves_unchanged(self, package_id: str) -> bool:
        return self._pin_types_by_id.get(package_id.casefold()) in {"pinning", "blocking"}

    def _installed_inventory_rows(
        self,
        scope: str,
        *,
        allow_recent: bool,
    ) -> list[dict[str, str]]:
        if allow_recent:
            cached = _RECENT_WINGET_INVENTORY.get(scope)
            if cached is not None:
                self.recent_inventory_hits += 1
                return cached

        refresh_token = _RECENT_WINGET_INVENTORY.begin_refresh(scope)
        command = [
            "winget",
            "list",
            "--scope",
            scope,
            "--accept-source-agreements",
            "--disable-interactivity",
        ]
        result, rows, parser_error, empty_result_proven = self._read_package_rows(
            command,
            ("Name", "Id", "Version", "Available", "Source"),
            updates=False,
            timeout=180,
        )
        code = normalized_exit_code(result.returncode)
        if code == WINGET_NO_APPLICATIONS_FOUND:
            _RECENT_WINGET_INVENTORY.store(scope, refresh_token, [])
            return []
        if result.returncode not in {0, 1}:
            detail = result.exception or result.output.strip() or "no diagnostic output"
            warning = f"{scope} inventory exited {result.returncode}: {detail[-500:]}"
            self.warnings.append(warning)
            self.mark_phase_incomplete(warning)
            return []
        if not rows and not parser_error:
            try:
                rows = parse_winget_table_consensus(
                    result.output,
                    ("Name", "Id", "Version", "Source"),
                )
            except ValueError as exc:
                parser_error = str(exc)
        if parser_error or (not rows and not empty_result_proven):
            warning = (
                f"parser drift detected while reading {scope} WinGet inventory; "
                "zero rows were not accepted without explicit empty-result evidence"
                + (f" ({parser_error})" if parser_error else "")
            )
            self.warnings.append(warning)
            self.mark_phase_incomplete(warning)
            return []
        _RECENT_WINGET_INVENTORY.store(scope, refresh_token, rows)
        return rows

    def _inventory(self, scope: str) -> tuple[set[tuple[str, str]], set[str], dict[str, set[str]]]:
        rows = self._installed_inventory_rows(scope, allow_recent=False)
        pairs = {
            (row["Id"].casefold(), row["Version"].casefold())
            for row in rows
            if row.get("Id") and row.get("Version")
        }
        ids = {row["Id"].casefold() for row in rows if row.get("Id")}
        names_by_id: dict[str, set[str]] = {}
        for row in rows:
            package_id = row.get("Id", "").casefold()
            name = row.get("Name", "").strip()
            if package_id and name:
                names_by_id.setdefault(package_id, set()).add(name.casefold())
        return pairs, ids, names_by_id

    def _upgrade_inventory(self, scope: str) -> tuple[list[dict[str, str]], str]:
        """Read one installed scope explicitly; WinGet's unscoped view can omit rows."""
        command = [
            "winget",
            "upgrade",
            "--scope",
            scope,
            "--include-pinned",
            "--accept-source-agreements",
            "--disable-interactivity",
        ]
        result, rows, parser_error, empty_result_proven = self._read_package_rows(
            command,
            ("Name", "Id", "Version", "Available", "Source"),
            updates=True,
            timeout=300,
        )
        code = normalized_exit_code(result.returncode)
        if code == WINGET_NO_APPLICATIONS_FOUND:
            return [], ""
        if result.returncode not in {0, 1}:
            detail = result.exception or result.output.strip() or "no diagnostic output"
            return [], f"{scope} update inventory exited {result.returncode}: {detail[-500:]}"
        if (
            not rows
            and not parser_error
            and winget_output_proves_empty_upgrade_inventory(result.output)
        ):
            return [], ""
        if parser_error or (not rows and not empty_result_proven):
            return (
                [],
                f"parser drift detected while reading {scope} WinGet update inventory; "
                "zero rows were not accepted without explicit empty-result evidence"
                + (f" ({parser_error})" if parser_error else ""),
            )
        for row in rows:
            row["_Scope"] = scope
        return rows, ""

    def _store_identity_names(
        self,
        rows: Sequence[dict[str, str]],
        installed_names_by_id: dict[str, set[str]],
    ) -> dict[str, set[str]]:
        """Resolve exact Store IDs because broad inventory may remap the same app."""
        names_by_id: dict[str, set[str]] = {}
        store_ids = {
            row.get("Id", "")
            for row in rows
            if row.get("Id")
            and row.get("Source", "").casefold() == "msstore"
            and len(installed_names_by_id.get(row["Id"].casefold(), set())) != 1
        }
        for package_id in sorted(store_ids, key=str.casefold):
            result = run_capture(
                [
                    "winget",
                    "list",
                    "--id",
                    package_id,
                    "--exact",
                    "--source",
                    "msstore",
                    "--accept-source-agreements",
                    "--disable-interactivity",
                ],
                timeout=180,
            )
            if result.returncode not in {0, 1}:
                detail = result.exception or result.output.strip() or "no diagnostic output"
                self.warnings.append(
                    f"exact Store inventory for {package_id} exited "
                    f"{result.returncode}: {detail[-500:]}"
                )
                continue
            try:
                exact_rows = parse_winget_table_consensus(
                    result.output,
                    ("Name", "Id", "Version"),
                )
            except ValueError as exc:
                self.warnings.append(
                    f"exact Store inventory for {package_id} was not trusted: {exc}"
                )
                continue
            folded_id = package_id.casefold()
            for row in exact_rows:
                if row.get("Id", "").casefold() != folded_id:
                    continue
                name = row.get("Name", "").strip()
                if name:
                    names_by_id.setdefault(folded_id, set()).add(name.casefold())
        return names_by_id

    def discover(self) -> list[UpdateItem]:
        self._pin_types_by_id = self._discover_pin_types()
        user_rows, user_error = self._upgrade_inventory("user")
        machine_rows, machine_error = self._upgrade_inventory("machine")
        for error in (user_error, machine_error):
            if error:
                self.warnings.append(error)
                self.mark_phase_incomplete(error)
        if user_error and machine_error:
            raise RuntimeError(f"WinGet scoped discovery failed: {user_error}; {machine_error}")
        # The dedicated Microsoft Store provider owns Store catalog rows.  Keep
        # WinGet focused on its community source so one Store update cannot be
        # presented twice under different provider labels.
        user_rows = [
            row for row in user_rows if row.get("Source", "").casefold() != MICROSOFT_STORE_SOURCE
        ]
        machine_rows = [
            row
            for row in machine_rows
            if row.get("Source", "").casefold() != MICROSOFT_STORE_SOURCE
        ]
        machine_pairs, machine_ids, machine_names = self._inventory("machine")
        user_pairs, user_ids, user_names = self._inventory("user")
        installed_names_by_id: dict[str, set[str]] = {}
        for inventory in (machine_names, user_names):
            for package_id, names in inventory.items():
                installed_names_by_id.setdefault(package_id, set()).update(names)
        for package_id, names in self._store_identity_names(
            [*user_rows, *machine_rows],
            installed_names_by_id,
        ).items():
            installed_names_by_id.setdefault(package_id, set()).update(names)
        installed_inventory = WindowsInstalledInventory.load()
        # discover_all follows discover on the same provider instance during a
        # combined scan. Preserve this registry snapshot so both views agree
        # exactly and avoid enumerating every uninstall hive twice.
        self._scan_installed_inventory = installed_inventory
        items = self._items_from_rows(
            [*user_rows, *machine_rows],
            machine_pairs,
            machine_ids,
            user_pairs,
            user_ids,
            installed_names_by_id,
            installed_inventory,
        )
        return self._suppress_stale_native_manager_rows(items)

    def discover_all(self) -> list[UpdateItem]:
        installed_inventory = self._scan_installed_inventory
        self._scan_installed_inventory = None
        if installed_inventory is None:
            installed_inventory = WindowsInstalledInventory.load()
        items: list[UpdateItem] = []
        seen: set[tuple[str, str, str, str]] = set()
        for scope in ("user", "machine"):
            rows = self._installed_inventory_rows(scope, allow_recent=True)
            for row in rows:
                package_id = row.get("Id", "").strip()
                current = row.get("Version", "").strip()
                if not valid_inventory_id(package_id):
                    self.warnings.append(
                        f"skipped unparseable or truncated WinGet installed entry (Id={package_id!r})"
                    )
                    continue
                source = row.get("Source", "").strip() or "winget"
                if source.casefold() == MICROSOFT_STORE_SOURCE:
                    continue
                key = (package_id.casefold(), current.casefold(), source.casefold(), scope)
                if key in seen:
                    continue
                seen.add(key)
                is_store_source = source.casefold() == "msstore"
                item = installed_inventory.enrich(
                    inventory_only_item(
                        provider=self.key,
                        name=row.get("Name", "").strip() or package_id,
                        package_id=package_id,
                        current=current,
                        source=source,
                        scope=scope,
                        requires_admin=scope == "machine" and not is_store_source,
                        instance=len(items),
                    )
                )
                if self._pin_leaves_unchanged(package_id):
                    item.status = "Pinned — left unchanged"
                    item.guidance = (
                        "WinGet is configured to leave this package unchanged."
                    )
                items.append(item)
        return items

    def _should_preflight_item(self, item: UpdateItem) -> bool:
        if item.provider != self.key:
            return False
        if item.source.casefold() == "msstore":
            return True
        if item.classification != CLASS_SIMPLE_UPGRADE:
            return True
        if item.package_id.casefold() in WINGET_PACKAGE_POLICIES:
            return True
        if item.installed_technology in {"msi", "exe", "mixed"}:
            return True
        return item.installed_for == "mixed"

    def _fetch_manifest_metadata(self, item: UpdateItem) -> WingetManifestMetadata:
        cache_key = (item.package_id.casefold(), (item.source or "winget").casefold(), item.available.casefold())
        cached = self._manifest_cache.get(cache_key)
        if cached is not None and time.monotonic() - cached[0] < 180:
            return cached[1]
        command = [
            "winget",
            "show",
            "--id",
            item.package_id,
            "--exact",
            "--accept-source-agreements",
            "--disable-interactivity",
        ]
        if valid_version(item.available):
            command.extend(("--version", item.available))
        if item.source:
            command.extend(("--source", item.source))
        result = run_capture(command, timeout=180)
        if result.returncode not in {0, 1} and not result.exception:
            time.sleep(0.35)
            retry_result = run_capture(command, timeout=180)
            if retry_result.returncode in {0, 1} or retry_result.exception:
                result = retry_result
            else:
                retry_result.output = "\n".join(
                    [
                        "Initial winget show attempt:",
                        result.output.strip() or f"exit {result.returncode}",
                        "",
                        "Retry winget show attempt:",
                        retry_result.output.strip() or f"exit {retry_result.returncode}",
                    ]
                )
                retry_result.duration_seconds = round(
                    result.duration_seconds + retry_result.duration_seconds + 0.35, 3
                )
                retry_result.started_at = result.started_at
                result = retry_result
        error = result.exception or ""
        if result.returncode not in {0, 1} and not error:
            error = (result.output.strip() or f"exit {result.returncode}")[-500:]
        metadata = parse_winget_show_metadata(
            result.output,
            package_id=item.package_id,
            source=item.source,
            returncode=result.returncode,
            error=error,
        )
        if not metadata.error:
            self._manifest_cache[cache_key] = (time.monotonic(), metadata)
        else:
            self._manifest_cache.pop(cache_key, None)
        return metadata

    def _preflight_items(self, items: Sequence[UpdateItem]) -> list[UpdateItem]:
        checked: list[UpdateItem | None] = [None] * len(items)
        representatives: dict[tuple[str, str, str], UpdateItem] = {}
        key_by_index: dict[int, tuple[str, str, str]] = {}
        for index, item in enumerate(items):
            if not self._should_preflight_item(item):
                checked[index] = item
                continue
            cache_key = (item.package_id.casefold(), (item.source or "winget").casefold(), item.available.casefold())
            representatives.setdefault(cache_key, item)
            key_by_index[index] = cache_key
        manifest_by_key: dict[tuple[str, str, str], WingetManifestMetadata | None] = {}
        max_workers = min(4, max(1, len(representatives)))
        with concurrent.futures.ThreadPoolExecutor(max_workers=max_workers) as executor:
            future_by_key = {
                executor.submit(self._fetch_manifest_metadata, item): cache_key
                for cache_key, item in representatives.items()
            }
            for future in concurrent.futures.as_completed(future_by_key):
                cache_key = future_by_key[future]
                try:
                    manifest_by_key[cache_key] = future.result()
                except Exception as exc:
                    item = representatives[cache_key]
                    self.warnings.append(
                        f"preflight manifest probe failed for {item.package_id}: "
                        f"{type(exc).__name__}: {exc}"
                    )
                    manifest_by_key[cache_key] = None
        for index, item in enumerate(items):
            if checked[index] is not None:
                continue
            manifest = manifest_by_key.get(key_by_index[index])
            checked[index] = apply_winget_preflight_prediction(item, manifest)
        return [item for item in checked if item is not None]

    def preflight_item(self, item: UpdateItem) -> UpdateItem:
        if not self._should_preflight_item(item):
            return item
        return apply_winget_preflight_prediction(item, self._fetch_manifest_metadata(item))

    def _suppress_stale_native_manager_rows(self, items: Sequence[UpdateItem]) -> list[UpdateItem]:
        """Hide a manager row when its native executable already has that release."""
        rustup_items = [item for item in items if item.package_id.casefold() == "rustlang.rustup"]
        if not rustup_items or not shutil.which("rustup"):
            return list(items)
        result = run_capture(["rustup", "--version"], timeout=30)
        match = re.search(r"(?im)^rustup\s+([A-Za-z0-9][A-Za-z0-9!+._~-]*)\b", result.output)
        if result.returncode != 0 or not match:
            return list(items)
        native_version = match.group(1)
        stale_keys = {
            item.key
            for item in rustup_items
            if item.available.casefold() == native_version.casefold()
        }
        if not stale_keys:
            return list(items)
        self.warnings.append(
            f"suppressed stale WinGet Rustup registration: rustup.exe is already {native_version}"
        )
        return [item for item in items if item.key not in stale_keys]

    def _items_from_rows(
        self,
        rows: Sequence[dict[str, str]],
        machine_pairs: set[tuple[str, str]],
        machine_ids: set[str],
        user_pairs: set[tuple[str, str]],
        user_ids: set[str],
        installed_names_by_id: dict[str, set[str]] | None = None,
        installed_inventory: WindowsInstalledInventory | None = None,
    ) -> list[UpdateItem]:
        updates: list[UpdateItem] = []
        counts: dict[tuple[str, str, str], int] = {}
        seen_rows: set[tuple[str, str, str, str, str]] = set()
        reported_dual: set[str] = set()
        reported_ambiguous_store: set[str] = set()
        reported_inventory_mismatch: set[str] = set()
        installed_names_by_id = installed_names_by_id or {}
        installed_inventory = installed_inventory or WindowsInstalledInventory.empty()
        update_scopes_by_id: dict[str, set[str]] = {}
        for row in rows:
            package_id = row.get("Id", "").casefold()
            scope_hint = row.get("_Scope", "")
            if package_id and scope_hint in {"user", "machine"}:
                update_scopes_by_id.setdefault(package_id, set()).add(scope_hint)
        for row in rows:
            package_id = row["Id"]
            version = row["Version"]
            if not valid_package_id(package_id) or "…" in package_id:
                self.warnings.append(
                    f"skipped unparseable or truncated WinGet entry (Id={package_id!r})"
                )
                continue
            folded_id = package_id.casefold()
            source = row["Source"] or "winget"
            scope_hint = row.get("_Scope", "")
            pair = (folded_id, version.casefold())
            inventory_reconciled = (
                pair in user_pairs
                if scope_hint == "user"
                else pair in machine_pairs
                if scope_hint == "machine"
                else pair in user_pairs or pair in machine_pairs
            )
            pinned_unchanged = self._pin_leaves_unchanged(package_id)
            pin_state_untrusted = self._pin_state_untrusted and not pinned_unchanged
            ambiguous_store_identity = (
                source.casefold() == "msstore"
                and len(installed_names_by_id.get(folded_id, set())) > 1
            )
            scopes = classify_winget_scopes(
                package_id,
                version,
                machine_pairs,
                machine_ids,
                user_pairs,
                user_ids,
            )
            duplicate_scopes = (
                len(update_scopes_by_id.get(folded_id, set())) > 1
                or len(scopes) == 2
                or (
                    source.casefold() != "msstore"
                    and folded_id in machine_ids
                    and folded_id in user_ids
                )
            )
            if not scopes:
                self.warnings.append(
                    f"could not prove user or machine scope for {package_id}; "
                    "the update is visible but not selected"
                )
                scopes = ("unknown",)
            elif duplicate_scopes and folded_id not in reported_dual:
                self.warnings.append(
                    f"{package_id} exists in both user and machine inventories; "
                    "showing exact-scope targets unchecked"
                )
                reported_dual.add(folded_id)
            if ambiguous_store_identity and folded_id not in reported_ambiguous_store:
                self.warnings.append(
                    f"{package_id} maps to multiple installed Microsoft Store names; "
                    "showing the candidate unchecked"
                )
                reported_ambiguous_store.add(folded_id)
            if not inventory_reconciled and folded_id not in reported_inventory_mismatch:
                self.warnings.append(
                    f"{package_id} update inventory did not match the separately read "
                    "installed version; showing it unchecked until a later scan agrees"
                )
                reported_inventory_mismatch.add(folded_id)
            for scope in scopes:
                signature = (
                    folded_id,
                    version.casefold(),
                    row["Available"].casefold(),
                    source.casefold(),
                    scope,
                )
                if signature in seen_rows:
                    self.warnings.append(
                        f"consolidated a duplicate WinGet output entry for {package_id} ({scope})"
                    )
                    continue
                seen_rows.add(signature)
                identity = (folded_id, scope, source.casefold())
                instance = counts.get(identity, 0)
                counts[identity] = instance + 1
                actionable = (
                    scope != "unknown"
                    and inventory_reconciled
                    and not pinned_unchanged
                    and not pin_state_untrusted
                )
                classification = (
                    CLASS_POLICY_BLOCKED
                    if pinned_unchanged
                    else CLASS_MANUAL_REVIEW
                    if pin_state_untrusted
                    else CLASS_DUPLICATE_INSTALL
                    if duplicate_scopes
                    else CLASS_AMBIGUOUS_IDENTITY
                    if ambiguous_store_identity
                    else CLASS_MANUAL_REVIEW
                    if not inventory_reconciled
                    else CLASS_SIMPLE_UPGRADE
                    if actionable
                    else CLASS_SCOPE_UNKNOWN
                )
                guidance = (
                    "WinGet is configured to leave this package unchanged."
                    if pinned_unchanged
                    else "WinGet's pin state could not be read reliably. The candidate is "
                    "visible for review but will not be recommended until a later scan "
                    "reads the pin configuration successfully."
                    if pin_state_untrusted
                    else "This exact package ID is registered in both current-user and "
                    "machine WinGet inventories. Decide which installation should remain "
                    "before choosing an exact scope."
                    if duplicate_scopes
                    else "This Store product ID maps to multiple installed names, so the "
                    "intended installation cannot be proven."
                    if ambiguous_store_identity
                    else "The update and installed-inventory reads did not agree on the "
                    "current version. A later scan can reconsider it automatically."
                    if not inventory_reconciled
                    else "WinGet inventory did not prove whether this registration belongs "
                    "to the current user or the machine."
                    if not actionable
                    else ""
                )
                is_store_source = source.casefold() == "msstore"
                item = installed_inventory.enrich(
                    UpdateItem(
                        provider=self.key,
                        name=row["Name"] or package_id,
                        package_id=package_id,
                        current=version,
                        available=row["Available"],
                        source=source,
                        scope=scope,
                        requires_admin=scope == "machine" and not is_store_source,
                        selected=(
                            actionable and not duplicate_scopes and not ambiguous_store_identity
                        ),
                        status=(
                            "Pinned — left unchanged"
                            if pinned_unchanged
                            else "Pin state unavailable — review"
                            if pin_state_untrusted
                            else "Duplicate user + machine installs"
                            if duplicate_scopes
                            else "Ambiguous Store identity"
                            if ambiguous_store_identity
                            else "Inventory changed — checking later"
                            if not inventory_reconciled
                            else "Ready"
                            if actionable
                            else "Scope unknown"
                        ),
                        instance=instance,
                        classification=classification,
                        guidance=guidance,
                    )
                )
                updates.append(apply_winget_package_policy(item))
        return updates

    def _build_update_command(
        self,
        item: UpdateItem,
        *,
        include_scope: bool,
        include_version: bool = True,
    ) -> list[str]:
        if item.scope not in {"user", "machine"}:
            raise ValueError(f"WinGet update scope is unresolved: {item.scope!r}")
        if not valid_version(item.available):
            raise ValueError(f"unsafe WinGet target version: {item.available!r}")
        command = [
            "winget",
            "upgrade",
            "--id",
            item.package_id,
            "--exact",
            "--silent",
            "--disable-interactivity",
            "--accept-source-agreements",
            "--accept-package-agreements",
            "--authentication-mode",
            "silentPreferred",
            "--include-unknown",
            "--verbose-logs",
        ]
        if item.source:
            command.extend(("--source", item.source))
        if include_version:
            command.extend(("--version", item.available))
        if include_scope:
            command.extend(("--scope", item.scope))
        return command

    def build_update_command(self, item: UpdateItem) -> list[str]:
        return self._build_update_command(
            item,
            include_scope=True,
            include_version=True,
        )

    def build_uninstall_command(self, item: UpdateItem) -> list[str]:
        if item.scope not in {"user", "machine"}:
            raise ValueError(f"WinGet uninstall scope is unresolved: {item.scope!r}")
        if not valid_package_id(item.package_id):
            raise ValueError(f"unsafe WinGet package id: {item.package_id!r}")
        if item.source.casefold() == "msstore" and item.scope != "user":
            raise ValueError("Microsoft Store removal is available only for a proven user scope")
        command = [
            "winget",
            "uninstall",
            "--id",
            item.package_id,
            "--exact",
            "--scope",
            item.scope,
            "--silent",
            "--disable-interactivity",
            "--accept-source-agreements",
            "--authentication-mode",
            "silentPreferred",
            "--verbose-logs",
        ]
        if item.source:
            if not valid_provider_source(item.source):
                raise ValueError(f"unsafe WinGet source: {item.source!r}")
            command.extend(("--source", item.source))
        return command

    @staticmethod
    def _can_retry_without_scope(item: UpdateItem, result: CommandResult) -> bool:
        """Retry when WinGet's explicit scope filter is the likely blocker.

        Some vendor manifests omit `Scope` even though their desktop installer
        can service the exact registration that WinGet just listed. Scoped
        upgrades can then return either no-applicable-package HRESULT. A single
        unscoped retry mirrors WinGet's ordinary exact-ID selection, but only for
        a unique, proven user or machine registration. Store, duplicate,
        ambiguous, held, and review paths remain excluded.
        """
        proven_scope = (
            item.scope == "user"
            and item.installed_for == "current-user"
            and not item.requires_admin
        ) or (
            item.scope == "machine"
            and item.installed_for == "machine"
            and item.requires_admin
        )
        return (
            normalized_exit_code(result.returncode) in WINGET_NOT_APPLICABLE_CODES
            and winget_scope_mismatch_evidence(result) is None
            and proven_scope
            and item.classification == CLASS_SIMPLE_UPGRADE
            and item.source.casefold() != "msstore"
            and not item.available_scope
        )

    def update(self, item: UpdateItem) -> CommandResult:
        if not valid_package_id(item.package_id):
            return immediate_command_error("unsafe package identifier")
        try:
            command = self.build_update_command(item)
        except (OSError, ValueError) as exc:
            return immediate_command_error(str(exc))
        first_result = run_capture(command, timeout=7200)
        annotate_winget_scope_mismatch(first_result)
        attempts: list[tuple[str, str, CommandResult]] = [
            ("scoped-pinned", "Scoped pinned attempt", first_result)
        ]

        def finish(result: CommandResult) -> CommandResult:
            result.attempts = tuple(
                command_attempt_diagnostic(strategy, label, attempt)
                for strategy, label, attempt in attempts
            )
            if len(attempts) == 1:
                return result
            result.output = "\n".join(
                [
                    "WinGet retried a proven single-scope package after an exact filtered "
                    "attempt returned no applicable installer.",
                    *(
                        line
                        for _strategy, label, attempt in attempts
                        for line in (
                            "",
                            f"{label}:",
                            attempt.output.strip() or "(no output)",
                        )
                    ),
                ]
            ).strip()
            result.started_at = first_result.started_at
            result.duration_seconds = round(
                sum(attempt.duration_seconds for _strategy, _label, attempt in attempts),
                3,
            )
            return result

        current_result = first_result
        if self._can_retry_without_scope(item, current_result):
            try:
                fallback_command = self._build_update_command(
                    item,
                    include_scope=False,
                    include_version=True,
                )
            except (OSError, ValueError) as exc:
                first_result.output = "\n".join(
                    [
                        first_result.output,
                        "",
                        "WinGet unscoped fallback was not attempted:",
                        str(exc),
                    ]
                ).strip()
                return finish(first_result)
            current_result = run_capture(fallback_command, timeout=7200)
            annotate_winget_scope_mismatch(current_result)
            attempts.append(("unscoped-pinned", "Unscoped pinned retry", current_result))
        if normalized_exit_code(current_result.returncode) == 0x8A150010:
            current_result.output += (
                "\nThe selected version could not be applied. Refresh the candidate "
                "before retrying; WinDevPilot has not substituted a different version."
            )
        return finish(current_result)


class MicrosoftStoreProvider(Provider):
    """Current-account Store inventory plus exact WinGet Store updates.

    The native PackageManager inventory is broader than ``winget list
    --source msstore`` because the latter only shows packages that the public
    Store catalog can correlate.  Mutations still use the supported WinGet
    ``msstore`` transport and are never elevated into another account.
    """

    key = MICROSOFT_STORE_PROVIDER_KEY
    label = "Microsoft Store"
    executable = "winget"
    default_enabled = True
    elevation_allowed = False
    success_codes = WINGET_SUCCESS_CODES
    already_current_codes = WINGET_ALREADY_CURRENT_CODES
    not_applicable_codes = WINGET_NOT_APPLICABLE_CODES
    canceled_codes = WINGET_CANCELED_CODES
    reboot_codes = WINGET_REBOOT_CODES
    note_by_code = WINGET_NOTE_BY_CODE

    def available(self) -> bool:
        return os.name == "nt" and shutil.which("powershell.exe") is not None

    def version_command(self) -> list[str]:
        if shutil.which("winget"):
            return ["winget", "--version"]
        return [
            "powershell.exe",
            "-NoLogo",
            "-NoProfile",
            "-NonInteractive",
            "-Command",
            "$PSVersionTable.PSVersion.ToString()",
        ]

    @staticmethod
    def _table_rows(output: str, *, updates: bool) -> list[dict[str, str]]:
        headers = (
            (
                ("Name", "Id", "Version", "Available", "Source"),
                ("Name", "Id", "Version", "Available"),
            )
            if updates
            else (
                ("Name", "Id", "Version", "Available", "Source"),
                ("Name", "Id", "Version", "Source"),
                ("Name", "Id", "Version"),
            )
        )
        for shape in headers:
            rows = parse_fixed_table(output, shape)
            if rows:
                return rows
        return []

    @staticmethod
    def _enrich_catalog_item(
        item: UpdateItem, installed_inventory: WindowsInstalledInventory
    ) -> UpdateItem:
        # Store product IDs are catalog identities, not uninstall registry IDs.
        # Let the normal inventory matcher consider both scopes, then restore
        # the Store operation scope to the launching account.
        item.scope = ""
        item = installed_inventory.enrich(item)
        item.scope = "user"
        item.requires_admin = False
        if not item.installed_for:
            item.installed_for = "current-user Store catalog"
        return item

    @staticmethod
    def _has_catalog_installation_conflict(item: UpdateItem) -> bool:
        """Reject a current-account Store action matched only to a machine desktop app."""

        return item.installed_for in {"machine", "mixed"} and item.installed_technology in {
            "exe",
            "msi",
            "mixed",
        }

    @classmethod
    def _apply_catalog_applicability_guard(cls, item: UpdateItem) -> UpdateItem:
        if not cls._has_catalog_installation_conflict(item):
            return item
        item.selected = False
        item.status = "Store offer does not match this desktop installation"
        item.classification = CLASS_SCOPE_OR_APPLICABILITY
        item.guidance = (
            "The Microsoft Store catalog listed a version for its current-account product, "
            "but the matching installed registration is a machine-wide desktop app. Those "
            "delivery channels and version schemes are not safely comparable, so "
            "WinDevPilot will not attempt this Store update. Use the desktop app's own "
            "updater or its original installer channel."
        )
        item.applicability_prediction = PREDICTION_NOT_APPLICABLE
        item.prediction_confidence = "high"
        item.prediction_source = "store-scope-technology-guard"
        item.prediction_reasons = (
            "the Store operation belongs to the launching account",
            f"the matching installed registration belongs to {item.installed_for}",
            f"the matching installed registration uses {item.installed_technology}",
        )
        return item

    def _actionable_catalog_update(self, item: UpdateItem) -> UpdateItem | None:
        item = self._apply_catalog_applicability_guard(item)
        if not self._has_catalog_installation_conflict(item):
            return item
        self.suppressed_updates.append(
            {
                "reason": "store-desktop-channel-conflict",
                "name": item.name,
                "package_id": item.package_id,
                "installed_version": item.current,
                "store_catalog_version": item.available,
                "installed_for": item.installed_for,
                "installed_technology": item.installed_technology,
                "installed_location": item.installed_location,
                "status": item.status,
            }
        )
        return None

    @staticmethod
    def _native_logo_path(record: Mapping[str, Any], item: UpdateItem) -> str:
        location_text = str(record.get("installed_location", "")).strip()
        location = Path(location_text) if location_text else None
        raw_logo = str(record.get("logo", "")).strip()
        if raw_logo:
            decoded = urllib.parse.unquote(raw_logo)
            parsed = urllib.parse.urlparse(decoded)
            if parsed.scheme.casefold() == "file":
                decoded = urllib.request.url2pathname(parsed.path)
            if re.match(r"^/[A-Za-z]:/", decoded):
                decoded = decoded[1:]
            candidate = Path(decoded)
            with contextlib.suppress(OSError):
                if (
                    candidate.is_absolute()
                    and candidate.is_file()
                    and (location is None or _path_is_within(candidate, location))
                ):
                    return str(candidate)
        fallback = appx_manifest_logo_path(item.package_id, 256, item.name)
        return str(fallback) if fallback is not None else ""

    def _catalog_rows(self, *, updates: bool) -> list[dict[str, str]]:
        if shutil.which("winget") is None:
            warning = (
                "WinGet is unavailable; native Store inventory is still shown, but exact "
                "Store catalog updates cannot be checked"
            )
            self.warnings.append(warning)
            if updates:
                self.mark_phase_incomplete(warning)
            return []
        command = [
            "winget",
            "upgrade" if updates else "list",
            "--source",
            MICROSOFT_STORE_SOURCE,
            "--accept-source-agreements",
            "--disable-interactivity",
        ]
        result = run_capture(command, timeout=300 if updates else 180)
        code = normalized_exit_code(result.returncode)
        if code == WINGET_NO_APPLICATIONS_FOUND:
            return []
        if result.returncode not in {0, 1}:
            raise RuntimeError(self._catalog_failure_message(result))
        rows = self._table_rows(result.output, updates=updates)
        if not rows and output_looks_like_package_table(result.output):
            raise RuntimeError("parser drift detected while reading Microsoft Store catalog")
        if not rows and updates and not winget_output_proves_empty_upgrade_inventory(
            result.output
        ):
            warning = (
                "Store catalog update listing returned zero rows without explicit "
                "empty-result evidence"
            )
            self.warnings.append(warning)
            self.mark_phase_incomplete(warning)
        return rows

    @staticmethod
    def _catalog_failure_message(result: CommandResult) -> str:
        code = normalized_exit_code(result.returncode)
        if code == WINGET_INTERNAL_ERROR:
            return (
                f"WinGet reported an internal error ({exit_code_hex(result.returncode)}) "
                "while reading the Microsoft Store catalog"
            )
        detail = result.exception or result.output.strip() or "no diagnostic output"
        return (
            f"Store catalog exited {exit_code_hex(result.returncode)} "
            f"({result.returncode}): {detail[-500:]}"
        )

    def discover(self) -> list[UpdateItem]:
        installed_inventory = WindowsInstalledInventory.load()
        updates: list[UpdateItem] = []
        for row in self._catalog_rows(updates=True):
            package_id = row.get("Id", "").strip()
            current = row.get("Version", "").strip()
            available = row.get("Available", "").strip()
            if (
                not valid_package_id(package_id)
                or not valid_version(current)
                or not valid_version(available)
            ):
                self.warnings.append(f"skipped unparseable Store update entry (Id={package_id!r})")
                continue
            item = self._actionable_catalog_update(
                self._enrich_catalog_item(
                    UpdateItem(
                        provider=self.key,
                        name=row.get("Name", "").strip() or package_id,
                        package_id=package_id,
                        current=current,
                        available=available,
                        source=MICROSOFT_STORE_SOURCE,
                        scope="user",
                        requires_admin=False,
                        selected=True,
                        status="Ready",
                        classification=CLASS_SIMPLE_UPGRADE,
                        installed_for="current-user Store catalog",
                        available_technology="Microsoft Store",
                        available_scope="current account",
                        available_upgrade_behavior="Store-managed",
                        metadata_sources=("winget-msstore",),
                        metadata_confidence="proven",
                        applicability_prediction=PREDICTION_ORDINARY,
                        prediction_confidence="high",
                        prediction_source="winget-msstore-upgrade",
                        prediction_reasons=(
                            "WinGet's Microsoft Store source listed this exact product ID "
                            "as updatable",
                        ),
                    ),
                    installed_inventory,
                ),
            )
            if item is None:
                continue
            updates.append(apply_winget_package_policy(item))
        return updates

    def _native_inventory(self) -> list[UpdateItem]:
        self.native_package_dates: dict[str, tuple[str, str]] = {}
        records, error = microsoft_store_package_inventory()
        if error:
            warning = f"native current-account inventory: {error}"
            self.warnings.append(warning)
            self.mark_phase_incomplete(warning)
            return []
        self.native_package_dates = windows_package_dates_from_records(records)
        items: list[UpdateItem] = []
        for record in records:
            if "date_only" in record:
                # Framework/non-Store dates cannot introduce inventory or Store actions.
                continue
            full_name = str(record.get("full_name", "")).strip()
            if not full_name or not valid_inventory_id(full_name):
                continue
            internal_name = str(record.get("name", "")).strip()
            display_name = str(record.get("display_name", "")).strip()
            if not display_name or display_name.casefold().startswith("ms-resource:"):
                display_name = internal_name or full_name.split("_", 1)[0]
            current = str(record.get("version", "")).strip() or "?"
            launchable = bool(record.get("launchable", False))
            item = inventory_only_item(
                provider=self.key,
                name=display_name,
                package_id=f"MSIX\\{full_name}",
                current=current,
                source="store-inventory",
                scope="user",
                requires_admin=False,
                instance=len(items),
                guidance=(
                    "Store-signed package registered to the launching Windows account. "
                    "Use Open Microsoft Store updates when no exact catalog update is listed."
                ),
            )
            item.status = "Microsoft Store app" if launchable else "Microsoft Store component"
            item.installed_for = "current-user"
            item.installed_technology = "msix"
            item.installed_location = str(record.get("installed_location", "")).strip()
            item.installed_timestamp, item.installed_timestamp_precision = (
                normalize_wall_clock_timestamp(record.get("installed_timestamp", ""))
            )
            if item.installed_timestamp:
                item.installed_date = (
                    dt.datetime.fromisoformat(item.installed_timestamp)
                    .astimezone()
                    .date()
                    .isoformat()
                )
                item.installed_date_source = "Windows PackageManager Package.InstalledDate"
            item.metadata_sources = (
                "windows-packagemanager",
                "microsoft-store-signature",
            )
            item.metadata_confidence = "proven"
            item.publisher = str(record.get("publisher", "")).strip()[:300]
            item.launch_app_ids = windows_package_launch_ids(record)
            description = re.sub(r"\s+", " ", str(record.get("description", "")).strip())
            if not description.casefold().startswith("ms-resource:"):
                item.description = description[:1000]
            item.architecture = str(record.get("architecture", "")).strip()[:80]
            item.icon_source = self._native_logo_path(record, item)
            items.append(item)
        return items

    def _catalog_inventory(self) -> list[UpdateItem]:
        installed_inventory = WindowsInstalledInventory.load()
        items: list[UpdateItem] = []
        try:
            rows = self._catalog_rows(updates=False)
        except RuntimeError as exc:
            self.warnings.append(
                f"{exc}; native current-account Store inventory was retained, but exact "
                "catalog correlation may be incomplete for this scan"
            )
            return items
        for row in rows:
            package_id = row.get("Id", "").strip()
            current = row.get("Version", "").strip()
            if not valid_package_id(package_id) or not current:
                continue
            item = self._enrich_catalog_item(
                inventory_only_item(
                    provider=self.key,
                    name=row.get("Name", "").strip() or package_id,
                    package_id=package_id,
                    current=current,
                    source=MICROSOFT_STORE_SOURCE,
                    scope="user",
                    requires_admin=False,
                    instance=len(items),
                    guidance=(
                        "Installed package correlated to an exact Microsoft Store product ID "
                        "for the launching Windows account."
                    ),
                ),
                installed_inventory,
            )
            item.status = "Microsoft Store catalog app"
            item.available_technology = "Microsoft Store"
            item.available_scope = "current account"
            item.metadata_sources = tuple(dict.fromkeys((*item.metadata_sources, "winget-msstore")))
            item.metadata_confidence = "proven"
            items.append(item)
        return items

    @staticmethod
    def _merge_inventory(
        native_items: Sequence[UpdateItem], catalog_items: Sequence[UpdateItem]
    ) -> list[UpdateItem]:
        """Prefer exact Store product IDs when one native package matches uniquely."""

        native_by_signature: dict[tuple[str, str], list[UpdateItem]] = {}
        for item in native_items:
            signature = (normalized_package_name(item.name), item.current.casefold())
            native_by_signature.setdefault(signature, []).append(item)
        replaced_native_keys: set[str] = set()
        merged_catalog: list[UpdateItem] = []
        for catalog in catalog_items:
            signature = (normalized_package_name(catalog.name), catalog.current.casefold())
            matches = native_by_signature.get(signature, [])
            if len(matches) == 1:
                native = matches[0]
                # Launch identity needs a physical package match, not a display-name join.
                if (
                    catalog.installed_location and native.installed_location
                    and os.path.normcase(catalog.installed_location.rstrip("\\/"))
                    == os.path.normcase(native.installed_location.rstrip("\\/"))
                    and catalog.installed_technology == "msix"
                ):
                    catalog.launch_app_ids = native.launch_app_ids
                replaced_native_keys.add(native.key)
                for field in (
                    "icon_source",
                    "installed_location",
                    "installed_date",
                    "installed_timestamp",
                    "installed_timestamp_precision",
                    "installed_registration_changed_at",
                    "installed_registration_changed_at_precision",
                    "installed_date_source",
                    "publisher",
                    "description",
                    "architecture",
                ):
                    if not getattr(catalog, field):
                        setattr(catalog, field, getattr(native, field))
                if catalog.installed_technology in {"", "unknown"}:
                    catalog.installed_technology = native.installed_technology
                catalog.metadata_sources = tuple(
                    dict.fromkeys((*catalog.metadata_sources, *native.metadata_sources))
                )
            merged_catalog.append(catalog)
        return [
            *(item for item in native_items if item.key not in replaced_native_keys),
            *merged_catalog,
        ]

    def discover_all(self) -> list[UpdateItem]:
        return self._merge_inventory(self._native_inventory(), self._catalog_inventory())

    def build_update_command(self, item: UpdateItem) -> list[str]:
        if item.source.casefold() != MICROSOFT_STORE_SOURCE:
            raise ValueError("native Store inventory has no exact selective update route")
        if self._has_catalog_installation_conflict(item):
            raise ValueError(
                "Microsoft Store cannot service this machine-wide desktop installation"
            )
        if not MICROSOFT_STORE_PRODUCT_ID_RE.fullmatch(item.package_id):
            raise ValueError(f"unsafe Microsoft Store product id: {item.package_id!r}")
        if not valid_version(item.available):
            raise ValueError(f"unsafe Microsoft Store target version: {item.available!r}")
        return [
            "winget",
            "upgrade",
            "--id",
            item.package_id,
            "--exact",
            "--source",
            MICROSOFT_STORE_SOURCE,
            "--version",
            item.available,
            "--silent",
            "--disable-interactivity",
            "--accept-source-agreements",
            "--accept-package-agreements",
            "--authentication-mode",
            "silentPreferred",
            "--include-unknown",
            "--verbose-logs",
        ]

    def build_uninstall_command(self, item: UpdateItem) -> list[str]:
        if item.source.casefold() != MICROSOFT_STORE_SOURCE:
            raise ValueError("native Store packages are not uninstalled from this inventory view")
        if not MICROSOFT_STORE_PRODUCT_ID_RE.fullmatch(item.package_id):
            raise ValueError(f"unsafe Microsoft Store product id: {item.package_id!r}")
        return [
            "winget",
            "uninstall",
            "--id",
            item.package_id,
            "--exact",
            "--source",
            MICROSOFT_STORE_SOURCE,
            "--silent",
            "--disable-interactivity",
            "--accept-source-agreements",
            "--authentication-mode",
            "silentPreferred",
            "--verbose-logs",
        ]

    def update(self, item: UpdateItem) -> CommandResult:
        result = super().update(item)
        result.attempts = (
            command_attempt_diagnostic(
                "store-product-pinned",
                "Exact Microsoft Store product attempt",
                result,
            ),
        )
        return result


def deduplicate_microsoft_store_inventory(items: Sequence[UpdateItem]) -> list[UpdateItem]:
    """Remove only WinGet inventory rows uniquely represented by Store evidence."""

    store_items = [item for item in items if item.provider == MICROSOFT_STORE_PROVIDER_KEY]
    if not store_items:
        return list(items)
    exact_store = {(item.package_id.casefold(), item.current.casefold()) for item in store_items}
    store_by_signature: dict[tuple[str, str], list[UpdateItem]] = {}
    for store_item in store_items:
        signature = (
            normalized_package_name(store_item.name),
            store_item.current.casefold(),
        )
        store_by_signature.setdefault(signature, []).append(store_item)
    deduplicated: list[UpdateItem] = []
    for item in items:
        if item.provider != WingetProvider.key:
            deduplicated.append(item)
            continue
        exact_match = (item.package_id.casefold(), item.current.casefold()) in exact_store
        signature = (normalized_package_name(item.name), item.current.casefold())
        signature_matches = store_by_signature.get(signature, [])
        same_location_match = bool(
            len(signature_matches) == 1
            and item.installed_location
            and signature_matches[0].installed_location
            and os.path.normcase(item.installed_location)
            == os.path.normcase(signature_matches[0].installed_location)
        )
        if item.source.casefold() == MICROSOFT_STORE_SOURCE or exact_match or same_location_match:
            continue
        deduplicated.append(item)
    return deduplicated


@dataclasses.dataclass(frozen=True, slots=True)
class PortableCatalogRefreshResult:
    records: tuple[PortableRecord, ...]
    checked: int
    matched: int
    unavailable: int


def _portable_catalog_http_url(value: str) -> str:
    candidate = str(value).strip()
    if not candidate or len(candidate) > 2048:
        return ""
    try:
        parsed = urllib.parse.urlparse(candidate)
    except ValueError:
        return ""
    if (
        parsed.scheme.casefold() not in {"http", "https"}
        or not parsed.netloc
        or parsed.username
        or parsed.password
    ):
        return ""
    return candidate


def _portable_catalog_search_id(
    record: PortableRecord,
    signature: PortableSignature | None,
    *,
    runner: Callable[..., CommandResult] = run_capture,
) -> tuple[str, str, str]:
    """Return only an explicit or unique exact-normalized WinGet identity."""

    if signature is not None and signature.winget_id:
        return signature.winget_id, "explicit WinGet package ID", ""
    result = runner(
        [
            "winget",
            "search",
            "--name",
            record.name,
            "--source",
            "winget",
            "--accept-source-agreements",
            "--disable-interactivity",
        ],
        timeout=120,
    )
    if result.returncode not in {0, 1}:
        detail = result.exception or result.output.strip() or f"exit {result.returncode}"
        return "", "", f"WinGet catalog search failed: {detail[-300:]}"
    rows = parse_fixed_table(
        result.output,
        ("Name", "Id", "Version", "Match", "Source"),
    )
    if not rows:
        rows = parse_fixed_table(result.output, ("Name", "Id", "Version", "Source"))
    identity_values = [record.name, Path(record.original_filename).stem]
    if signature is not None:
        identity_values.extend(
            (signature.key, signature.display_name, *signature.metadata_names)
        )
    identities = {
        normalized_package_name(value)
        for value in identity_values
        if normalized_package_name(value)
    }
    accepted: dict[str, str] = {}
    for row in rows:
        package_id = row.get("Id", "").strip()
        name = row.get("Name", "").strip()
        if not valid_package_id(package_id):
            continue
        normalized_fields = {
            normalized_package_name(name),
            normalized_package_name(package_id.rsplit(".", 1)[-1]),
        }
        if identities.intersection(normalized_fields):
            accepted.setdefault(package_id.casefold(), package_id)
    if len(accepted) == 1:
        return next(iter(accepted.values())), "unique exact normalized WinGet match", ""
    if accepted:
        return "", "", "multiple exact-looking WinGet catalog matches were found"
    return "", "", "no high-confidence WinGet catalog match was found"


def refresh_portable_catalog_record(
    record: PortableRecord,
    *,
    runner: Callable[..., CommandResult] = run_capture,
) -> PortableRecord:
    """Attach conservative WinGet catalog metadata without inventing an update route."""

    signature = _portable_signature_by_key(record.app_key)
    checked_at = utc_now_iso()
    package_id, match_basis, search_error = _portable_catalog_search_id(
        record,
        signature,
        runner=runner,
    )
    if not package_id:
        return refresh_portable_release_clue(
            dataclasses.replace(
                record,
                catalog_package_id="",
                catalog_name="",
                catalog_available_version="",
                catalog_homepage="",
                catalog_download_url="",
                catalog_match_basis="",
                catalog_checked_at=checked_at,
                catalog_error=search_error,
            )
        )
    show_result = runner(
        [
            "winget",
            "show",
            "--id",
            package_id,
            "--exact",
            "--source",
            "winget",
            "--accept-source-agreements",
            "--disable-interactivity",
        ],
        timeout=180,
    )
    metadata = parse_winget_show_metadata(
        show_result.output,
        package_id=package_id,
        source="winget",
        returncode=show_result.returncode,
        error=show_result.exception,
    )
    version = metadata.raw_fields.get("version", "").strip()
    if not valid_version(version):
        version = ""
    name = metadata.raw_fields.get("name", "").strip()
    homepage = _portable_catalog_http_url(
        metadata.raw_fields.get("homepage", "")
        or metadata.raw_fields.get("publisherurl", "")
    )
    download_url = _portable_catalog_http_url(metadata.raw_fields.get("installerurl", ""))
    error = ""
    if signature is None:
        installer_types = {
            normalized_manifest_value(value) for value in metadata.installer_types
        }
        if "portable" not in installer_types:
            return refresh_portable_release_clue(
                dataclasses.replace(
                    record,
                    catalog_package_id="",
                    catalog_name="",
                    catalog_available_version="",
                    catalog_homepage="",
                    catalog_download_url="",
                    catalog_match_basis="",
                    catalog_checked_at=checked_at,
                    catalog_error=(
                        "the exact-looking WinGet candidate did not declare a portable "
                        "or nested-portable installer"
                    ),
                )
            )
        manifest_publisher = metadata.raw_fields.get("publisher", "").strip()
        record_publisher = record.publisher.strip()
        if manifest_publisher and record_publisher:
            manifest_identity = normalized_package_name(manifest_publisher)
            record_identity = normalized_package_name(record_publisher)
            publisher_agrees = (
                manifest_identity == record_identity
                or (
                    min(len(manifest_identity), len(record_identity)) >= 5
                    and (
                        manifest_identity in record_identity
                        or record_identity in manifest_identity
                    )
                    and min(len(manifest_identity), len(record_identity))
                    / max(len(manifest_identity), len(record_identity))
                    >= 0.6
                )
            )
            if not publisher_agrees:
                return refresh_portable_release_clue(
                    dataclasses.replace(
                        record,
                        catalog_package_id="",
                        catalog_name="",
                        catalog_available_version="",
                        catalog_homepage="",
                        catalog_download_url="",
                        catalog_match_basis="",
                        catalog_checked_at=checked_at,
                        catalog_error=(
                            "the exact-looking WinGet candidate publisher disagreed with "
                            "the executable publisher"
                        ),
                    )
                )
        match_basis += "; manifest declares portable installer"
    if show_result.returncode not in {0, 1} or not version:
        detail = (
            show_result.exception
            or metadata.error
            or show_result.output.strip()
            or f"exit {show_result.returncode}"
        )
        error = f"WinGet catalog details were unavailable: {detail[-300:]}"
    return dataclasses.replace(
        record,
        catalog_package_id=package_id,
        catalog_name=name,
        catalog_available_version=version,
        catalog_homepage=homepage,
        catalog_download_url=download_url,
        catalog_match_basis=match_basis,
        catalog_checked_at=checked_at,
        catalog_error=error,
    )


def refresh_portable_catalog_records(
    records: Sequence[PortableRecord],
    *,
    runner: Callable[..., CommandResult] = run_capture,
) -> PortableCatalogRefreshResult:
    """Refresh each portable app identity once and reuse it for duplicate copies."""

    refreshed_by_key: dict[str, PortableRecord] = {}
    output: list[PortableRecord] = []
    checked = 0
    for record in records:
        if portable_catalog_metadata_is_fresh(record):
            output.append(record)
            continue
        template = refreshed_by_key.get(record.app_key)
        if template is None:
            template = refresh_portable_catalog_record(record, runner=runner)
            refreshed_by_key[record.app_key] = template
            checked += 1
        output.append(
            dataclasses.replace(
                record,
                catalog_package_id=template.catalog_package_id,
                catalog_name=template.catalog_name,
                catalog_available_version=template.catalog_available_version,
                catalog_homepage=template.catalog_homepage,
                catalog_download_url=template.catalog_download_url,
                catalog_match_basis=template.catalog_match_basis,
                catalog_checked_at=template.catalog_checked_at,
                catalog_error=template.catalog_error,
            )
        )
    matched = sum(bool(record.catalog_available_version) for record in output)
    return PortableCatalogRefreshResult(
        records=tuple(output),
        checked=checked,
        matched=matched,
        unavailable=len(output) - matched,
    )


def npm_blocked_install_script_packages(output: str) -> tuple[str, ...]:
    packages = tuple(
        dict.fromkeys(
            match.group("package")
            for match in re.finditer(
                r"(?im)^\s*npm warn install-scripts\s+"
                r"(?P<package>@[^/@\s]+/[^@\s]+|[^@\s]+)@[^\s(]+\s+\(",
                output,
            )
        )
    )
    return packages


def compact_npm_output_for_ui(output: str) -> str:
    """Keep npm outcomes and warnings visible while retaining network chatter only on disk."""

    kept: list[str] = []
    for line in output.splitlines():
        folded = line.strip().casefold()
        if (
            folded.startswith("npm http ")
            or folded.startswith("npm verbose ")
            or folded.startswith("npm info using ")
            or folded == "npm info ok"
            or folded.startswith("npm warn install-scripts")
        ):
            continue
        if not folded and (not kept or not kept[-1].strip()):
            continue
        kept.append(line)
    while kept and not kept[-1].strip():
        kept.pop()
    return "\n".join(kept)


def compact_process_output_for_ui(
    output: str,
    *,
    provider_key: str = "",
    max_chars: int = MAX_UI_PROCESS_OUTPUT_CHARS,
) -> str:
    """Bound chatty process output in Tk while retaining the durable log copy."""

    compacted = (
        compact_npm_output_for_ui(output)
        if provider_key == NpmProvider.key
        else output.strip()
    )
    if len(compacted) <= max_chars:
        return compacted
    head_chars = max_chars * 3 // 5
    tail_chars = max_chars - head_chars
    head = compacted[:head_chars].rsplit("\n", maxsplit=1)[0] or compacted[:head_chars]
    tail = compacted[-tail_chars:].split("\n", maxsplit=1)[-1] or compacted[-tail_chars:]
    omitted = max(0, len(compacted) - len(head) - len(tail))
    return (
        f"{head}\n"
        f"… {omitted:,} process-output characters hidden here; full bounded output is "
        "retained in the session logs …\n"
        f"{tail}"
    )


def command_result_event_payload(
    item: UpdateItem, entry: dict[str, Any]
) -> tuple[UpdateItem, dict[str, Any], str]:
    """Prepare non-Tk result text on the operation worker before publication."""

    return (
        item,
        entry,
        compact_process_output_for_ui(
            str(entry.get("output", "")).strip(),
            provider_key=item.provider,
        ),
    )


def npm_post_update_integrity(
    item: UpdateItem, global_root: Path | None = None
) -> tuple[dict[str, Any], Path | None]:
    """Verify the installed manifest and declared command targets without executing them."""

    root = global_root
    root_probe: CommandResult | None = None
    if root is None:
        root_probe = run_capture(["npm", "root", "--global"], timeout=30)
        root_text = root_probe.output.strip().splitlines()
        if root_probe.returncode != 0 or not root_text:
            return (
                {
                    "verified": False,
                    "error": root_probe.exception
                    or root_probe.output.strip()
                    or "npm global root was unavailable",
                    "probe": command_diagnostic_fields(root_probe),
                },
                None,
            )
        root = Path(root_text[-1]).expanduser()
    package_path = root.joinpath(*item.package_id.split("/"))
    if not _path_is_within(package_path, root):
        return ({"verified": False, "error": "npm package path escaped global root"}, root)
    manifest_path = package_path / "package.json"
    try:
        if manifest_path.stat().st_size > 2 * 1024 * 1024:
            raise ValueError("package.json exceeded 2 MiB")
        manifest = json.loads(manifest_path.read_text(encoding="utf-8"))
        if not isinstance(manifest, dict):
            raise ValueError("package.json root was not an object")
    except (OSError, TypeError, ValueError) as exc:
        return (
            {
                "verified": False,
                "error": f"{type(exc).__name__}: {exc}",
                "manifest": str(manifest_path),
            },
            root,
        )
    installed_version = str(manifest.get("version", "")).strip()
    raw_bin = manifest.get("bin", {})
    if isinstance(raw_bin, str):
        bin_targets = {item.package_id.rsplit("/", maxsplit=1)[-1]: raw_bin}
    elif isinstance(raw_bin, dict):
        bin_targets = {
            str(name): str(relative)
            for name, relative in raw_bin.items()
            if isinstance(name, str) and isinstance(relative, str)
        }
    else:
        bin_targets = {}
    missing: list[str] = []
    present: list[str] = []
    for name, relative in sorted(bin_targets.items()):
        target = package_path / relative
        if not _path_is_within(target, package_path):
            missing.append(f"{name} (unsafe target)")
        elif target.is_file():
            present.append(name)
        else:
            missing.append(name)
    return (
        {
            "verified": bool(installed_version),
            "installed_version": installed_version,
            "target_version": item.available,
            "version_matches": installed_version.casefold() == item.available.casefold(),
            "declared_commands": sorted(bin_targets),
            "present_command_targets": present,
            "missing_command_targets": missing,
            "manifest": str(manifest_path),
            "root_probe": (
                command_diagnostic_fields(root_probe) if root_probe is not None else {}
            ),
        },
        root,
    )


class NpmProvider(Provider):
    key = "npm"
    label = "npm (global user)"
    executable = "npm"

    def result_warnings(self, result: CommandResult) -> list[str]:
        folded_output = result.output.casefold()
        if (
            "npm warn install-scripts" in folded_output
            and "had install scripts blocked" in folded_output
        ):
            blocked = npm_blocked_install_script_packages(result.output)
            detail = (
                f": {', '.join(blocked)}"
                if blocked and len(blocked) <= 3
                else f" ({len(blocked)} packages)"
                if blocked
                else ""
            )
            return [
                "npm blocked dependency install scripts"
                f"{detail}; review them before explicitly allowing any script"
            ]
        return []

    def discover(self) -> list[UpdateItem]:
        result = run_capture(["npm", "outdated", "--global", "--depth=0", "--json"], timeout=300)
        if result.returncode not in {0, 1}:
            raise RuntimeError(result.exception or result.output.strip())
        start = result.output.find("{")
        if start < 0:
            raise RuntimeError("npm returned no JSON result")
        data, _end = json.JSONDecoder().raw_decode(result.output[start:])
        if not isinstance(data, dict) or "error" in data:
            raise RuntimeError("npm returned an error or invalid result: " + result.output[-500:])
        return self._items_from_data(data)

    def discover_all(self) -> list[UpdateItem]:
        result = run_capture(["npm", "list", "--global", "--depth=0", "--json"], timeout=300)
        if result.returncode not in {0, 1}:
            raise RuntimeError(result.exception or result.output.strip())
        start = result.output.find("{")
        if start < 0:
            raise RuntimeError("npm returned no JSON result")
        data, _end = json.JSONDecoder().raw_decode(result.output[start:])
        if not isinstance(data, dict) or "error" in data:
            raise RuntimeError("npm returned an error or invalid result: " + result.output[-500:])
        if result.returncode != 0 or data.get("problems"):
            self.mark_phase_incomplete("npm reported an incomplete dependency tree")
        dependencies = data.get("dependencies", {})
        if not isinstance(dependencies, dict):
            raise RuntimeError("npm returned invalid dependencies")
        items: list[UpdateItem] = []
        for package_id, info in sorted(
            dependencies.items(), key=lambda pair: str(pair[0]).casefold()
        ):
            if not valid_package_id(str(package_id)):
                self.mark_phase_incomplete("npm contained an invalid package identity")
                self.warnings.append(f"skipped unsafe npm package id: {package_id!r}")
                continue
            version = str(info.get("version", "")) if isinstance(info, dict) else ""
            if not valid_version(version):
                self.mark_phase_incomplete("npm contained an invalid installed version")
                continue
            items.append(
                inventory_only_item(
                    provider=self.key,
                    name=str(package_id),
                    package_id=str(package_id),
                    current=version,
                    source="npm global",
                    instance=len(items),
                )
            )
        return items

    def _items_from_data(self, data: Any) -> list[UpdateItem]:
        if not isinstance(data, dict):
            raise ValueError("npm outdated returned a non-object JSON payload")
        updates: list[UpdateItem] = []
        for package_id, raw_info in sorted(data.items(), key=lambda pair: pair[0].casefold()):
            if not valid_package_id(package_id):
                self.mark_phase_incomplete("npm contained an invalid package identity")
                self.warnings.append(f"skipped unsafe npm package id: {package_id!r}")
                continue
            registrations = raw_info if isinstance(raw_info, list) else [raw_info]
            for instance, info in enumerate(registrations):
                if not isinstance(info, dict):
                    self.mark_phase_incomplete("npm contained a malformed registration")
                    self.warnings.append(f"skipped malformed npm registration for {package_id}")
                    continue
                available = str(info.get("latest") or info.get("wanted") or "")
                if not valid_version(available):
                    self.mark_phase_incomplete("npm contained an invalid target version")
                    self.warnings.append(
                        f"skipped {package_id}: unsafe registry version {available!r}"
                    )
                    continue
                updates.append(
                    UpdateItem(
                        provider=self.key,
                        name=package_id,
                        package_id=package_id,
                        current=str(info.get("current", "?")),
                        available=available,
                        source="npm global",
                        scope="user",
                        instance=instance,
                    )
                )
        return updates

    def build_update_command(self, item: UpdateItem) -> list[str]:
        if not valid_version(item.available):
            raise ValueError(f"unsafe npm version string: {item.available!r}")
        target = f"{item.package_id}@{item.available}"
        return [
            "npm",
            "install",
            "--global",
            target,
            "--no-audit",
            "--no-fund",
            "--loglevel=verbose",
        ]

    def build_uninstall_command(self, item: UpdateItem) -> list[str]:
        if item.scope != "user" or item.requires_admin:
            raise ValueError("npm global packages may be removed only for the current user")
        if not valid_package_id(item.package_id):
            raise ValueError(f"unsafe npm package id: {item.package_id!r}")
        return ["npm", "uninstall", "--global", item.package_id, "--loglevel=verbose"]


class BunProvider(Provider):
    key = "bun"
    label = "Bun (global user)"
    executable = "bun"

    @staticmethod
    def _global_package_json() -> Path:
        return Path.home() / ".bun" / "install" / "global" / "package.json"

    def discover(self) -> list[UpdateItem]:
        global_manifest = self._global_package_json()
        if not global_manifest.exists():
            # This is Bun's normal empty state before any global package is installed.
            return []
        result = run_capture(
            [
                "bun",
                "outdated",
                "--global",
                "--cwd",
                str(global_manifest.parent),
                "--no-progress",
            ],
            timeout=300,
        )
        if result.returncode not in {0, 1}:
            if "nothing outdated" in result.output.casefold():
                return []
            raise RuntimeError(result.exception or result.output.strip())
        return self._items_from_output(result.output)

    def discover_all(self) -> list[UpdateItem]:
        global_manifest = self._global_package_json()
        if not global_manifest.exists():
            # Match discover(): no manifest means no global Bun inventory yet.
            return []
        try:
            data = json.loads(global_manifest.read_text(encoding="utf-8"))
        except (OSError, json.JSONDecodeError) as exc:
            raise RuntimeError(f"Bun global manifest parse failed: {exc}") from exc
        items: list[UpdateItem] = []
        for section in ("dependencies", "devDependencies", "optionalDependencies"):
            dependencies = data.get(section, {}) if isinstance(data, dict) else {}
            if not isinstance(dependencies, dict):
                continue
            for package_id, version in sorted(
                dependencies.items(), key=lambda pair: str(pair[0]).casefold()
            ):
                if not valid_package_id(str(package_id)):
                    self.warnings.append(f"Bun skipped unsafe package id: {package_id!r}")
                    continue
                items.append(
                    inventory_only_item(
                        provider=self.key,
                        name=str(package_id),
                        package_id=str(package_id),
                        current=str(version),
                        source=f"Bun global {section}",
                        instance=len(items),
                    )
                )
        return items

    def _items_from_output(self, output: str) -> list[UpdateItem]:
        updates: list[UpdateItem] = []
        rows = parse_fixed_table(output, ("Package", "Current", "Update", "Latest"))
        if not rows:
            rows = parse_fixed_table(output, ("Package", "Current", "Latest"))
        for instance, row in enumerate(rows):
            package_id = row.get("Package", "").strip()
            current = row.get("Current", "").strip()
            available = (row.get("Latest") or row.get("Update") or "").strip()
            if not package_id or package_id.casefold() in {"package", "dependencies"}:
                continue
            if not valid_package_id(package_id):
                self.warnings.append(f"Bun skipped unsafe package id: {package_id!r}")
                continue
            if not valid_version(current) or not valid_version(available):
                self.warnings.append(f"Bun skipped {package_id}: unsafe version text")
                continue
            if current.casefold() == available.casefold():
                continue
            updates.append(
                UpdateItem(
                    provider=self.key,
                    name=package_id,
                    package_id=package_id,
                    current=current,
                    available=available,
                    source="Bun global / npm registry",
                    scope="user",
                    requires_admin=False,
                    instance=instance,
                )
            )
        return updates

    def build_update_command(self, item: UpdateItem) -> list[str]:
        if item.scope != "user" or item.requires_admin:
            raise ValueError("Bun global packages may update only for the current user")
        if not valid_package_id(item.package_id):
            raise ValueError(f"unsafe Bun package id: {item.package_id!r}")
        if not valid_version(item.available):
            raise ValueError(f"unsafe Bun version string: {item.available!r}")
        return [
            "bun",
            "add",
            "--global",
            "--no-progress",
            f"{item.package_id}@{item.available}",
        ]

    def build_uninstall_command(self, item: UpdateItem) -> list[str]:
        if item.scope != "user" or item.requires_admin:
            raise ValueError("Bun global packages may be removed only for the current user")
        if not valid_package_id(item.package_id):
            raise ValueError(f"unsafe Bun package id: {item.package_id!r}")
        return ["bun", "remove", "--global", "--no-progress", item.package_id]


class ScoopProvider(Provider):
    key = "scoop"
    label = "Scoop"
    executable = "scoop"
    _source_refresh_lock: ClassVar[threading.Lock] = threading.Lock()
    _source_refresh_attempted_at: ClassVar[float] = 0.0
    _source_refresh_warning: ClassVar[str] = ""

    def _refresh_sources_if_needed(self) -> None:
        """Refresh Scoop's core scripts and bucket indexes at most once per process TTL.

        A stale bucket can hide an update even though every subsequent local
        command succeeds. Refresh failures are non-fatal: cached bucket data is
        still useful and the warning tells the user why it may be incomplete.
        """
        with self._source_refresh_lock:
            now = time.monotonic()
            if (
                self._source_refresh_attempted_at
                and now - self._source_refresh_attempted_at
                < SCOOP_SOURCE_REFRESH_TTL_SECONDS
            ):
                if self._source_refresh_warning:
                    self.warnings.append(self._source_refresh_warning)
                return
            type(self)._source_refresh_attempted_at = now
            result = run_capture(
                ["scoop", "update"],
                timeout=SCOOP_SOURCE_REFRESH_TIMEOUT_SECONDS,
            )
            if result.returncode == 0:
                type(self)._source_refresh_warning = ""
                return
            detail = clean_output(
                result.exception or result.output.strip() or f"exit {result.returncode}"
            )
            detail = " ".join(detail.split())
            if len(detail) > 320:
                detail = f"…{detail[-319:]}"
            type(self)._source_refresh_warning = (
                "Scoop core/bucket refresh failed; update discovery used cached metadata"
                + (f": {detail}" if detail else "")
            )
            self.warnings.append(self._source_refresh_warning)

    @staticmethod
    def _items_from_status_output(output: str) -> list[UpdateItem]:
        rows = parse_fixed_table(
            output,
            (
                "Name",
                "Installed Version",
                "Latest Version",
                "Missing Dependencies",
                "Info",
            ),
        )
        updates: list[UpdateItem] = []
        for row in rows:
            package_id = row.get("Name", "").strip()
            current = row.get("Installed Version", "").strip()
            available = row.get("Latest Version", "").strip()
            if (
                not valid_package_id(package_id)
                or not current
                or not available
                or not re.search(r"\d", current + available)
            ):
                continue
            updates.append(
                UpdateItem(
                    provider="scoop",
                    name=package_id,
                    package_id=package_id,
                    current=current,
                    available=available,
                    source="Scoop",
                    scope="user",
                )
            )
        return updates

    def discover(self) -> list[UpdateItem]:
        self._refresh_sources_if_needed()
        result = run_capture(["scoop", "status", "-l"], timeout=600)
        if result.returncode != 0:
            raise RuntimeError(result.exception or result.output.strip())
        return self._items_from_status_output(result.output)

    def discover_all(self) -> list[UpdateItem]:
        result = run_capture(["scoop", "list"], timeout=600)
        if result.returncode != 0:
            raise RuntimeError(result.exception or result.output.strip())
        rows = parse_fixed_table(result.output, ("Name", "Version", "Source", "Updated"))
        items: list[UpdateItem] = []
        for row in rows:
            package_id = row.get("Name", "").strip()
            current = row.get("Version", "").strip()
            if not valid_package_id(package_id):
                continue
            items.append(
                inventory_only_item(
                    provider=self.key,
                    name=package_id,
                    package_id=package_id,
                    current=current,
                    source=row.get("Source", "").strip() or "Scoop",
                    instance=len(items),
                )
            )
        return items

    def build_update_command(self, item: UpdateItem) -> list[str]:
        return ["scoop", "update", item.package_id]

    def build_uninstall_command(self, item: UpdateItem) -> list[str]:
        if item.scope != "user" or item.requires_admin:
            raise ValueError("Scoop packages may be removed only in the current-user context")
        if not valid_package_id(item.package_id):
            raise ValueError(f"unsafe Scoop package id: {item.package_id!r}")
        return ["scoop", "uninstall", item.package_id]


class CargoProvider(Provider):
    key = "cargo"
    label = "Cargo (installed crates)"
    executable = "cargo-install-update"
    default_enabled = False

    def discover(self) -> list[UpdateItem]:
        result = run_capture(["cargo", "install-update", "--list"], timeout=1800)
        if result.returncode != 0:
            raise RuntimeError(result.exception or result.output.strip())
        updates: list[UpdateItem] = []
        row_re = re.compile(r"^(\S+)\s+(v?\S+)\s+(v?\S+)\s+Yes\s*$", re.IGNORECASE)
        for line in result.output.splitlines():
            match = row_re.match(line.strip())
            if not match:
                continue
            package_id, current, available = match.groups()
            if not valid_package_id(package_id):
                continue
            updates.append(
                UpdateItem(
                    provider=self.key,
                    name=package_id,
                    package_id=package_id,
                    current=current,
                    available=available,
                    source="crates.io",
                    scope="user",
                )
            )
        return updates

    def discover_all(self) -> list[UpdateItem]:
        result = run_capture(["cargo", "install", "--list"], timeout=600)
        if result.returncode != 0:
            raise RuntimeError(result.exception or result.output.strip())
        items: list[UpdateItem] = []
        row_re = re.compile(r"^(?P<name>\S+)\s+v(?P<version>\S+):\s*$")
        for line in result.output.splitlines():
            match = row_re.match(line.strip())
            if not match:
                continue
            package_id = match.group("name")
            current = match.group("version")
            if not valid_package_id(package_id):
                self.warnings.append(f"Cargo skipped unsafe crate name: {package_id!r}")
                continue
            items.append(
                inventory_only_item(
                    provider=self.key,
                    name=package_id,
                    package_id=package_id,
                    current=current,
                    source="crates.io",
                    instance=len(items),
                )
            )
        return items

    def build_update_command(self, item: UpdateItem) -> list[str]:
        return ["cargo", "install-update", item.package_id]

    def build_uninstall_command(self, item: UpdateItem) -> list[str]:
        if item.scope != "user" or item.requires_admin:
            raise ValueError("Cargo binaries may be removed only for the current user")
        if not valid_package_id(item.package_id):
            raise ValueError(f"unsafe Cargo package id: {item.package_id!r}")
        return ["cargo", "uninstall", item.package_id]


class VcpkgProvider(Provider):
    key = "vcpkg"
    label = "vcpkg classic packages"
    executable = "vcpkg"
    default_enabled = False
    _NO_CLASSIC_WARNING = (
        "vcpkg is installed without a classic-mode instance; manifest projects remain "
        "outside WinDevPilot's global scan"
    )

    @staticmethod
    def _classic_instance_unavailable(output: str) -> bool:
        folded = output.casefold()
        return (
            "does not have a classic mode instance" in folded
            or (
                "could not locate a manifest" in folded
                and "vcpkg.json" in folded
            )
        )

    def discover(self) -> list[UpdateItem]:
        result = run_capture(["vcpkg", "upgrade"], timeout=600)
        if result.returncode != 0:
            if self._classic_instance_unavailable(result.output):
                self.warnings.append(self._NO_CLASSIC_WARNING)
                return []
            detail = result.exception or result.output.strip()
            raise RuntimeError(detail)
        return self._items_from_output(result.output)

    def discover_all(self) -> list[UpdateItem]:
        result = run_capture(["vcpkg", "list"], timeout=600)
        if result.returncode != 0:
            if self._classic_instance_unavailable(result.output):
                self.warnings.append(self._NO_CLASSIC_WARNING)
                return []
            raise RuntimeError(result.exception or result.output.strip())
        items: list[UpdateItem] = []
        for line in result.output.splitlines():
            parts = line.strip().split(None, 2)
            if len(parts) < 2:
                continue
            package_id, current = parts[0], parts[1]
            if not SAFE_VCPKG_PACKAGE_RE.fullmatch(package_id):
                self.warnings.append(f"vcpkg skipped unsafe package id: {package_id!r}")
                continue
            items.append(
                inventory_only_item(
                    provider=self.key,
                    name=package_id,
                    package_id=package_id,
                    current=current,
                    source="vcpkg classic",
                    instance=len(items),
                )
            )
        return items

    def _items_from_output(self, output: str) -> list[UpdateItem]:
        updates: list[UpdateItem] = []
        row_re = re.compile(
            r"^\s*\*?\s*(?P<name>[A-Za-z0-9][A-Za-z0-9+._-]*(?::[A-Za-z0-9][A-Za-z0-9+._-]*)?)"
            r"\s+(?P<current>[A-Za-z0-9][A-Za-z0-9!+._~#-]*)\s*->\s*"
            r"(?P<available>[A-Za-z0-9][A-Za-z0-9!+._~#-]*)\s*$"
        )
        for line in output.splitlines():
            match = row_re.match(line.strip())
            if not match:
                continue
            package_id = match.group("name")
            current = match.group("current")
            available = match.group("available")
            if not SAFE_VCPKG_PACKAGE_RE.fullmatch(package_id):
                self.warnings.append(f"vcpkg skipped unsafe package id: {package_id!r}")
                continue
            if not valid_version(current.replace("#", ".")) or not valid_version(
                available.replace("#", ".")
            ):
                self.warnings.append(f"vcpkg skipped {package_id}: unsafe version text")
                continue
            updates.append(
                UpdateItem(
                    provider=self.key,
                    name=package_id,
                    package_id=package_id,
                    current=current,
                    available=available,
                    source="vcpkg classic",
                    scope="user",
                    requires_admin=False,
                    classification=CLASS_MANUAL_REVIEW,
                    status="vcpkg classic - review dependency rebuild",
                    guidance=(
                        "vcpkg upgrades can rebuild dependent C/C++ libraries. "
                        "WinDevPilot shows classic-mode candidates but leaves them "
                        "out of recommended bulk selection."
                    ),
                    instance=len(updates),
                )
            )
        return updates

    def build_update_command(self, item: UpdateItem) -> list[str]:
        if item.scope != "user" or item.requires_admin:
            raise ValueError("vcpkg classic packages may update only in the current context")
        if not SAFE_VCPKG_PACKAGE_RE.fullmatch(item.package_id):
            raise ValueError(f"unsafe vcpkg package id: {item.package_id!r}")
        return ["vcpkg", "upgrade", item.package_id, "--no-dry-run"]

    def build_uninstall_command(self, item: UpdateItem) -> list[str]:
        if item.scope != "user" or item.requires_admin:
            raise ValueError("vcpkg classic packages may be removed only in the current context")
        if not SAFE_VCPKG_PACKAGE_RE.fullmatch(item.package_id):
            raise ValueError(f"unsafe vcpkg package id: {item.package_id!r}")
        return ["vcpkg", "remove", item.package_id]

    def update(self, item: UpdateItem) -> CommandResult:
        # vcpkg package IDs may include `name:triplet`; the base Provider.update
        # guard intentionally rejects colon syntax for other package managers.
        try:
            command = self.build_update_command(item)
        except (OSError, ValueError) as exc:
            return immediate_command_error(str(exc))
        return run_capture(command, timeout=7200)


RUSTUP_CHECK_UPDATE_RE = re.compile(
    r"^(?P<toolchain>\S+)\s+-\s+update available\s*:\s+"
    r"(?P<current>[A-Za-z0-9][A-Za-z0-9!+._~-]*)"
    r"(?:\s+\((?P<current_revision>[^)\r\n]{1,128})\))?\s+->\s+"
    r"(?P<available>[A-Za-z0-9][A-Za-z0-9!+._~-]*)"
    r"(?:\s+\((?P<available_revision>[^)\r\n]{1,128})\))?\s*$",
    re.IGNORECASE,
)
RUSTUP_ROLLBACK_MISSING_COMPONENT_RE = re.compile(
    r"(?is)\brolling back changes\b.*?"
    r"\bfailure removing component\s+'(?P<component>[^'\r\n]{1,128})'.*?"
    r"\bdirectory does not exist:\s*'(?P<path>[^'\r\n]{1,260})'"
)
RUSTUP_UPDATE_AVAILABLE = 100


def rustup_damaged_toolchain_evidence(output: str) -> tuple[str, str] | None:
    """Return bounded evidence for Rustup's broken component-removal state."""

    match = RUSTUP_ROLLBACK_MISSING_COMPONENT_RE.search(output)
    if not match:
        return None
    return match.group("component").strip(), match.group("path").strip()


class RustupProvider(Provider):
    key = "rustup"
    label = "Rustup toolchains (current user)"
    executable = "rustup"

    def version_command(self) -> list[str]:
        return ["rustup", "--version"]

    def discover(self) -> list[UpdateItem]:
        result = run_capture(["rustup", "check"], timeout=300)
        updates = self._items_from_output(result.output)
        # `rustup check` returns 100 when one or more updates are available. A
        # rustup-only update is intentionally owned by the WinGet provider, but
        # it is still a valid Rustup check result rather than a provider error.
        if not self._check_result_is_acceptable(
            result.returncode,
            result.output,
            updates,
        ):
            raise RuntimeError(result.exception or result.output.strip())
        return updates

    @classmethod
    def _check_result_is_acceptable(
        cls,
        returncode: int,
        output: str,
        updates: Sequence[UpdateItem],
    ) -> bool:
        if returncode == 0:
            return True
        if returncode != RUSTUP_UPDATE_AVAILABLE:
            return False
        return bool(updates) or cls._has_recognized_self_update(output)

    @staticmethod
    def _has_recognized_self_update(output: str) -> bool:
        for line in output.splitlines():
            match = RUSTUP_CHECK_UPDATE_RE.match(line.strip())
            if not match or match.group("toolchain").casefold() != "rustup":
                continue
            if match.group("current").casefold() != match.group("available").casefold():
                return True
        return False

    def discover_all(self) -> list[UpdateItem]:
        result = run_capture(["rustup", "toolchain", "list"], timeout=120)
        if result.returncode != 0:
            raise RuntimeError(result.exception or result.output.strip())
        items: list[UpdateItem] = []
        for line in result.output.splitlines():
            toolchain = re.sub(r"\s+\([^)]*\)\s*$", "", line.strip()).strip()
            if not toolchain:
                continue
            if not valid_package_id(toolchain):
                self.warnings.append(f"Rustup skipped unsafe toolchain name: {toolchain!r}")
                continue
            items.append(
                inventory_only_item(
                    provider=self.key,
                    name=f"Rust toolchain: {toolchain}",
                    package_id=toolchain,
                    current="installed",
                    source="rustup",
                    instance=len(items),
                )
            )
        return items

    def _items_from_output(self, output: str) -> list[UpdateItem]:
        updates: list[UpdateItem] = []
        for line in output.splitlines():
            match = RUSTUP_CHECK_UPDATE_RE.match(line.strip())
            if not match:
                continue
            toolchain = match.group("toolchain")
            current = match.group("current")
            available = match.group("available")
            current_revision = (match.group("current_revision") or "").strip()
            available_revision = (match.group("available_revision") or "").strip()
            if toolchain.casefold() == "rustup":
                continue
            if not valid_package_id(toolchain):
                self.warnings.append(f"skipped unsafe Rustup toolchain name: {toolchain!r}")
                continue
            if not valid_version(current) or not valid_version(available):
                self.warnings.append(f"skipped {toolchain}: unsafe Rustup version output")
                continue
            current_display = (
                f"{current} ({current_revision})" if current_revision else current
            )
            available_display = (
                f"{available} ({available_revision})" if available_revision else available
            )
            if current_display.casefold() == available_display.casefold():
                self.warnings.append(
                    f"skipped {toolchain}: Rustup reported identical update identities"
                )
                continue
            updates.append(
                UpdateItem(
                    provider=self.key,
                    name=f"Rust toolchain: {toolchain}",
                    package_id=toolchain,
                    current=current_display,
                    available=available_display,
                    source="rustup",
                    scope="user",
                )
            )
        return updates

    def build_update_command(self, item: UpdateItem) -> list[str]:
        if item.scope != "user" or item.requires_admin:
            raise ValueError("Rustup toolchains may update only for the current user")
        if not valid_package_id(item.package_id):
            raise ValueError(f"unsafe Rustup toolchain name: {item.package_id!r}")
        command = ["rustup"]
        if self.debug_mode:
            command.append("--verbose")
        command.extend(("update", item.package_id, "--no-self-update"))
        return command

    def build_uninstall_command(self, item: UpdateItem) -> list[str]:
        if item.scope != "user" or item.requires_admin:
            raise ValueError("Rustup toolchains may be removed only for the current user")
        if not valid_package_id(item.package_id) or item.package_id.casefold() == "rustup":
            raise ValueError(f"unsafe Rustup toolchain name: {item.package_id!r}")
        return ["rustup", "toolchain", "uninstall", item.package_id]

    def status_hint(self, result: CommandResult) -> str:
        if rustup_damaged_toolchain_evidence(result.output):
            return "Damaged Rust toolchain - reinstall manually"
        return super().status_hint(result)


PIP_INVENTORY_JSON_BEGIN = "WinDevPilot_PIP_INVENTORY_JSON_BEGIN"
PIP_INVENTORY_JSON_END = "WinDevPilot_PIP_INVENTORY_JSON_END"
PIP_USER_SITE_INVENTORY_SCRIPT = rf"""
import csv
import importlib.metadata as metadata
import io
import json
import os
import re
import site

BEGIN = {PIP_INVENTORY_JSON_BEGIN!r}
END = {PIP_INVENTORY_JSON_END!r}
SKIP_PARTS = {{
    "benchmark", "benchmarks", "demo", "demos", "doc", "docs",
    "example", "examples", "sample", "samples", "test", "tests",
}}
GENERIC_ART_NAMES = {{
    "appicon", "applicationicon", "brand", "favicon", "icon", "logo",
}}

def normalized(value):
    return re.sub(r"[^a-z0-9]+", "", value.casefold())

def image_extent(path):
    try:
        with open(path, "rb") as stream:
            header = stream.read(24)
            if header.startswith(b"\x89PNG\r\n\x1a\n") and header[12:16] == b"IHDR":
                return max(
                    int.from_bytes(header[16:20], "big"),
                    int.from_bytes(header[20:24], "big"),
                )
            if header[:4] == b"\x00\x00\x01\x00" and len(header) >= 6:
                stream.seek(6)
                extents = []
                for _index in range(int.from_bytes(header[4:6], "little")):
                    entry = stream.read(16)
                    if len(entry) != 16:
                        break
                    extents.append(max(entry[0] or 256, entry[1] or 256))
                return max(extents, default=0)
    except OSError:
        pass
    return 0

def package_aliases(distribution, package_name):
    aliases = {{normalized(package_name)}}
    for raw_line in (distribution.read_text("top_level.txt") or "").splitlines():
        top_level = raw_line.replace("\\", "/").split("/", 1)[0]
        alias = normalized(top_level)
        if len(alias) >= 4:
            aliases.add(alias)
    return {{alias for alias in aliases if alias}}

def match_strength(stem_key, keys):
    if stem_key in keys:
        return 3
    if any(len(key) >= 5 and stem_key.startswith(key) for key in keys):
        return 2
    if any(len(key) >= 6 and key in stem_key for key in keys):
        return 1
    return 0

def best_icon(distribution, package_name, user_site):
    package_key = normalized(package_name)
    if not package_key:
        return ""
    aliases = package_aliases(distribution, package_name)
    record = distribution.read_text("RECORD") or ""
    candidates = []
    for row in csv.reader(io.StringIO(record)):
        if not row:
            continue
        relative = row[0].replace("\\", "/")
        suffix = os.path.splitext(relative)[1].casefold()
        if suffix not in {{".exe", ".ico", ".png"}}:
            continue
        parts = [part.casefold() for part in relative.split("/") if part not in {{"", "."}}]
        path = os.path.abspath(str(distribution.locate_file(row[0])))
        try:
            if os.path.commonpath((user_site, path)) != user_site:
                continue
            size = os.path.getsize(path)
        except (OSError, ValueError):
            continue
        maximum_size = 64 * 1024 * 1024 if suffix == ".exe" else 8 * 1024 * 1024
        if not 32 <= size <= maximum_size:
            continue
        stem_key = normalized(os.path.splitext(os.path.basename(path))[0])
        package_match = match_strength(stem_key, {{package_key}})
        alias_match = match_strength(stem_key, aliases)
        path_keys = {{normalized(part) for part in parts[:-1]}}
        path_match = any(
            key == path_key
            or (
                len(key) >= 5
                and len(path_key) >= 5
                and (key in path_key or path_key in key)
                and min(len(key), len(path_key)) / max(len(key), len(path_key)) >= 0.55
            )
            for key in aliases
            for path_key in path_keys
        )
        if suffix == ".exe":
            # Console entry points in Scripts are generic Python/distlib
            # launchers. A native executable inside the distribution itself is
            # useful only when its filename identifies that package/module.
            if "scripts" in parts or alias_match < 2:
                continue
            relevance = 70 + alias_match * 5
        elif package_match:
            # Treat ``project.png`` and ``project_large.png`` as equally
            # attributable, then let actual dimensions choose the useful art.
            relevance = 120 if package_match >= 2 else 100
        elif stem_key in GENERIC_ART_NAMES and path_match:
            relevance = 75
        elif alias_match >= 2:
            relevance = 65 + alias_match * 5
        else:
            continue
        # Docs and test fixtures are normally screenshots or expected-output
        # images. Keep one only when the artwork itself has a strong package
        # name, rather than discarding an explicitly bundled logo by location.
        if any(part in SKIP_PARTS for part in parts) and max(package_match, alias_match) < 2:
            continue
        extent = image_extent(path)
        meets_target = extent >= 144
        size_rank = -extent if meets_target else extent
        native_image = suffix in {{".ico", ".png"}}
        candidates.append(
            (relevance, native_image, meets_target, size_rank, size, path.casefold(), path)
        )
    return max(candidates, default=(0, False, False, 0, 0, "", ""))[-1]

user_site = os.path.normcase(os.path.abspath(site.getusersitepackages()))
items = []
warnings = []
try:
    distributions = metadata.distributions(path=[user_site])
    for distribution in distributions:
        try:
            name = str(distribution.metadata.get("Name") or "").strip()
            version = str(distribution.version or "").strip()
            if not name:
                continue
            items.append({{
                "name": name,
                "version": version,
                "icon_source": best_icon(distribution, name, user_site),
            }})
        except Exception as error:
            warnings.append(f"{{type(error).__name__}} while reading one distribution")
except Exception as error:
    warnings.append(f"{{type(error).__name__}} while reading the user site")
print(BEGIN)
print(json.dumps({{"schema": 1, "items": items, "warnings": warnings}}, separators=(",", ":")))
print(END)
""".strip()


def pip_user_site_inventory() -> tuple[list[dict[str, str]], list[str]]:
    """Read user-site package versions and conservative local logo assets in one pass."""

    result = run_capture(
        [*user_pip_python_prefix(), "-c", PIP_USER_SITE_INVENTORY_SCRIPT],
        timeout=120,
    )
    if result.returncode != 0:
        raise RuntimeError(result.exception or result.output.strip())
    payload = sentinel_json_payload(
        result.output,
        PIP_INVENTORY_JSON_BEGIN,
        PIP_INVENTORY_JSON_END,
    )
    if not isinstance(payload, dict) or payload.get("schema") != 1:
        raise ValueError("pip user-site inventory returned an unsupported payload")
    raw_items = payload.get("items", [])
    raw_warnings = payload.get("warnings", [])
    if not isinstance(raw_items, list) or not isinstance(raw_warnings, list):
        raise ValueError("pip user-site inventory returned malformed collections")
    items: list[dict[str, str]] = []
    for raw_item in raw_items:
        if not isinstance(raw_item, dict):
            continue
        items.append(
            {
                "name": str(raw_item.get("name", "")),
                "version": str(raw_item.get("version", "")),
                "icon_source": str(raw_item.get("icon_source", "")),
            }
        )
    return items, [str(warning) for warning in raw_warnings if warning]


class PipProvider(Provider):
    key = "pip"
    label = "pip (default Python user site)"
    executable = "py"
    default_enabled = False

    def available(self) -> bool:
        try:
            user_pip_python_prefix()
            return True
        except FileNotFoundError:
            return False

    def version_command(self) -> list[str]:
        return [*user_pip_python_prefix(), "-m", "pip", "--version"]

    def discover(self) -> list[UpdateItem]:
        result = run_capture(
            [
                *user_pip_python_prefix(),
                "-m",
                "pip",
                "list",
                "--outdated",
                "--user",
                "--format=json",
                "--disable-pip-version-check",
            ],
            # A hung index/network operation must not hold an entire provider
            # scan open for half an hour. Five minutes remains generous for a
            # read-only outdated-package listing.
            timeout=300,
        )
        if result.returncode != 0:
            raise RuntimeError(result.exception or result.output.strip())
        start = result.output.find("[")
        if start < 0:
            return []
        data, _end = json.JSONDecoder().raw_decode(result.output[start:])
        if not isinstance(data, list):
            raise ValueError("pip list returned a non-list JSON payload")
        updates: list[UpdateItem] = []
        counts: dict[str, int] = {}
        for entry in data:
            if not isinstance(entry, dict):
                self.warnings.append("skipped malformed pip outdated entry")
                continue
            package_id = str(entry.get("name", ""))
            available = str(entry.get("latest_version", ""))
            if not valid_package_id(package_id):
                self.warnings.append(f"skipped unsafe pip package id: {package_id!r}")
                continue
            if not valid_version(available):
                self.warnings.append(f"skipped {package_id}: unsafe index version {available!r}")
                continue
            folded_id = package_id.casefold()
            instance = counts.get(folded_id, 0)
            counts[folded_id] = instance + 1
            updates.append(
                UpdateItem(
                    provider=self.key,
                    name=package_id,
                    package_id=package_id,
                    current=str(entry.get("version", "?")),
                    available=available,
                    source="pip user site",
                    scope="user",
                    selected=False,
                    instance=instance,
                )
            )
        return updates

    def discover_all(self) -> list[UpdateItem]:
        data, warnings = pip_user_site_inventory()
        self.warnings.extend(warnings)
        items: list[UpdateItem] = []
        for entry in data:
            package_id = str(entry.get("name", ""))
            current = str(entry.get("version", ""))
            if not valid_package_id(package_id):
                self.warnings.append(f"pip skipped unsafe package id: {package_id!r}")
                continue
            item = inventory_only_item(
                provider=self.key,
                name=package_id,
                package_id=package_id,
                current=current,
                source="pip user site",
                instance=len(items),
            )
            icon_source = str(entry.get("icon_source", ""))
            if icon_source and Path(icon_source).is_file():
                item.icon_source = icon_source
                item.metadata_sources = ("pip-record",)
                item.metadata_confidence = "proven"
            items.append(item)
        return items

    def build_update_command(self, item: UpdateItem) -> list[str]:
        if not valid_version(item.available):
            raise ValueError(f"unsafe pip version string: {item.available!r}")
        return [
            *user_pip_python_prefix(),
            "-m",
            "pip",
            "install",
            "--user",
            "--upgrade",
            "--disable-pip-version-check",
            "--no-input",
            "--no-color",
            "--no-cache-dir",
            "--verbose",
            f"{item.package_id}=={item.available}",
        ]

    def build_uninstall_command(self, item: UpdateItem) -> list[str]:
        if item.scope != "user" or item.requires_admin:
            raise ValueError("pip user-site packages may be removed only for the current user")
        if not valid_package_id(item.package_id):
            raise ValueError(f"unsafe pip package id: {item.package_id!r}")
        return [
            *user_pip_python_prefix(),
            "-m",
            "pip",
            "uninstall",
            "--yes",
            "--disable-pip-version-check",
            "--no-input",
            "--no-color",
            "--verbose",
            item.package_id,
        ]

    def result_warnings(self, result: CommandResult) -> list[str]:
        if not self.succeeded(result):
            return []
        effects = parse_pip_install_output(result.output)
        warnings: list[str] = []
        if effects.resolver_conflicts:
            warnings.append("pip reported dependency conflicts after installing the target package")
        if effects.scripts_not_on_path:
            warnings.append("pip installed script entry points outside PATH")
        warnings.extend(
            f"pip emitted an ERROR-level warning despite exit 0: {warning}"
            for warning in effects.generic_error_warnings
        )
        return warnings

    def status_hint(self, result: CommandResult) -> str:
        if self.succeeded(result) and self.result_warnings(result):
            return "Updated with pip dependency warnings"
        return super().status_hint(result)


class PipxProvider(Provider):
    key = "pipx"
    label = "pipx apps (isolated user tools)"
    executable = "pipx"
    default_enabled = True

    def discover(self) -> list[UpdateItem]:
        self._inventory_data_for_next_phase: Any = None
        result = run_capture(["pipx", "list", "--json"], timeout=180)
        if result.returncode != 0:
            raise RuntimeError(result.exception or result.output.strip())
        try:
            data = json.loads(result.output)
        except json.JSONDecodeError as exc:
            raise RuntimeError(f"pipx JSON parse failed: {exc}") from exc
        self._inventory_data_for_next_phase = data
        return self._items_from_data(data)

    def discover_all(self) -> list[UpdateItem]:
        data = getattr(self, "_inventory_data_for_next_phase", None)
        self._inventory_data_for_next_phase = None
        if data is None:
            result = run_capture(["pipx", "list", "--json"], timeout=180)
            if result.returncode != 0:
                raise RuntimeError(result.exception or result.output.strip())
            try:
                data = json.loads(result.output)
            except json.JSONDecodeError as exc:
                raise RuntimeError(f"pipx JSON parse failed: {exc}") from exc
        venvs = data.get("venvs", {}) if isinstance(data, dict) else {}
        if not isinstance(venvs, dict):
            return []
        items: list[UpdateItem] = []
        for package_id, record in sorted(venvs.items(), key=lambda pair: str(pair[0]).casefold()):
            if not valid_package_id(str(package_id)):
                self.warnings.append(f"pipx skipped unsafe package name: {package_id!r}")
                continue
            main_package: Any = {}
            if isinstance(record, dict):
                metadata = record.get("metadata", {})
                if isinstance(metadata, dict):
                    main_package = metadata.get("main_package", {})
            current = (
                str(main_package.get("package_version", ""))
                if isinstance(main_package, dict)
                else ""
            )
            items.append(
                inventory_only_item(
                    provider=self.key,
                    name=str(package_id),
                    package_id=str(package_id),
                    current=current,
                    source="pipx",
                    instance=len(items),
                )
            )
        return items

    def _items_from_data(self, data: Any) -> list[UpdateItem]:
        venvs = data.get("venvs", {}) if isinstance(data, dict) else {}
        if not isinstance(venvs, dict):
            return []
        updates: list[UpdateItem] = []
        for package_id, record in sorted(venvs.items(), key=lambda pair: str(pair[0]).casefold()):
            if not valid_package_id(str(package_id)):
                self.warnings.append(f"pipx skipped unsafe package name: {package_id!r}")
                continue
            if not isinstance(record, dict):
                continue
            metadata = record.get("metadata", {})
            if not isinstance(metadata, dict):
                metadata = {}
            main_package = metadata.get("main_package", {})
            if not isinstance(main_package, dict):
                main_package = {}
            if bool(main_package.get("pinned")) or bool(record.get("pinned")):
                self.warnings.append(f"pipx skipped pinned package: {package_id}")
                continue
            current = str(
                main_package.get("package_version")
                or record.get("package_version")
                or record.get("version")
                or ""
            ).strip()
            if not valid_version(current):
                self.warnings.append(f"pipx skipped {package_id}: installed version unavailable")
                continue
            pypi_name = str(main_package.get("package") or package_id).strip()
            if not valid_package_id(pypi_name):
                self.warnings.append(
                    f"pipx skipped unsafe PyPI distribution name for {package_id}: {pypi_name!r}"
                )
                continue
            available, warning = latest_pypi_version(pypi_name)
            if warning:
                self.warnings.append(f"pipx {warning}")
            if not available:
                continue
            comparison = compare_semantic_versions(available, current)
            if comparison is None:
                self.warnings.append(
                    f"pipx skipped {package_id}: versions could not be ordered safely "
                    f"({current!r} -> {available!r})"
                )
                continue
            if comparison <= 0:
                continue
            updates.append(
                UpdateItem(
                    provider=self.key,
                    name=str(package_id),
                    package_id=str(package_id),
                    current=current,
                    available=available,
                    source="PyPI via pipx",
                    scope="user",
                    requires_admin=False,
                )
            )
        return updates

    def build_update_command(self, item: UpdateItem) -> list[str]:
        if item.scope != "user" or item.requires_admin:
            raise ValueError("pipx packages may update only for the current user")
        if not valid_package_id(item.package_id):
            raise ValueError(f"unsafe pipx package name: {item.package_id!r}")
        return ["pipx", "upgrade", item.package_id]

    def build_uninstall_command(self, item: UpdateItem) -> list[str]:
        if item.scope != "user" or item.requires_admin:
            raise ValueError("pipx apps may be removed only for the current user")
        if not valid_package_id(item.package_id):
            raise ValueError(f"unsafe pipx app name: {item.package_id!r}")
        return ["pipx", "uninstall", item.package_id]


class DotNetToolProvider(Provider):
    key = "dotnet-tool"
    label = ".NET global tools"
    executable = "dotnet"

    def discover(self) -> list[UpdateItem]:
        self._inventory_rows_for_next_phase: list[dict[str, str]] | None = None
        result = run_capture(["dotnet", "tool", "list", "--global"], timeout=180)
        if result.returncode != 0:
            raise RuntimeError(result.exception or result.output.strip())
        rows = self._parse_tool_list(result.output)
        self._inventory_rows_for_next_phase = rows
        updates: list[UpdateItem] = []
        for instance, row in enumerate(rows):
            package_id = row["id"]
            current = row["version"]
            available, warning = latest_nuget_listed_version(package_id)
            if warning:
                self.warnings.append(f".NET tool {warning}")
            if not available:
                continue
            comparison = compare_semantic_versions(available, current)
            if comparison is None:
                self.warnings.append(
                    f".NET tool skipped {package_id}: versions could not be ordered safely "
                    f"({current!r} -> {available!r})"
                )
                continue
            if comparison <= 0:
                continue
            updates.append(
                UpdateItem(
                    provider=self.key,
                    name=package_id,
                    package_id=package_id,
                    current=current,
                    available=available,
                    source="NuGet / dotnet global tool",
                    scope="user",
                    requires_admin=False,
                    instance=instance,
                )
            )
        return updates

    def discover_all(self) -> list[UpdateItem]:
        rows = getattr(self, "_inventory_rows_for_next_phase", None)
        self._inventory_rows_for_next_phase = None
        if rows is None:
            result = run_capture(["dotnet", "tool", "list", "--global"], timeout=180)
            if result.returncode != 0:
                raise RuntimeError(result.exception or result.output.strip())
            rows = self._parse_tool_list(result.output)
        items: list[UpdateItem] = []
        for row in rows:
            package_id = row["id"]
            items.append(
                inventory_only_item(
                    provider=self.key,
                    name=package_id,
                    package_id=package_id,
                    current=row["version"],
                    source="dotnet global tool",
                    instance=len(items),
                )
            )
        return items

    @staticmethod
    def _parse_tool_list(output: str) -> list[dict[str, str]]:
        rows: list[dict[str, str]] = []
        for line in output.splitlines():
            stripped = line.strip()
            if not stripped or stripped.startswith("-"):
                continue
            if "Package Id" in stripped and "Version" in stripped:
                continue
            parts = re.split(r"\s{2,}", stripped, maxsplit=2)
            if len(parts) < 2:
                continue
            package_id, version = parts[0].strip(), parts[1].strip()
            if not valid_package_id(package_id) or not valid_version(version):
                continue
            rows.append({"id": package_id, "version": version})
        return rows

    def build_update_command(self, item: UpdateItem) -> list[str]:
        if item.scope != "user" or item.requires_admin:
            raise ValueError(".NET global tools may update only for the current user")
        if not valid_package_id(item.package_id):
            raise ValueError(f"unsafe .NET tool package id: {item.package_id!r}")
        if not valid_version(item.available):
            raise ValueError(f"unsafe .NET tool version: {item.available!r}")
        return [
            "dotnet",
            "tool",
            "update",
            item.package_id,
            "--global",
            "--version",
            item.available,
        ]

    def build_uninstall_command(self, item: UpdateItem) -> list[str]:
        if item.scope != "user" or item.requires_admin:
            raise ValueError(".NET global tools may be removed only for the current user")
        if not valid_package_id(item.package_id):
            raise ValueError(f"unsafe .NET tool package id: {item.package_id!r}")
        return ["dotnet", "tool", "uninstall", item.package_id, "--global"]


class UvToolProvider(Provider):
    key = "uv-tool"
    label = "uv tools (isolated user tools)"
    executable = "uv"

    def discover(self) -> list[UpdateItem]:
        result = run_capture(["uv", "--color", "never", "tool", "list", "--outdated"], timeout=180)
        if result.returncode != 0 and "--outdated" in result.output:
            installed = run_capture(["uv", "--color", "never", "tool", "list"], timeout=180)
            if installed.returncode == 0:
                count = sum(
                    1
                    for line in installed.output.splitlines()
                    if line.strip() and not line.lstrip().startswith("-")
                )
                self.warnings.append(
                    "uv is installed, but this uv version does not support "
                    f"`uv tool list --outdated`; {count} uv tool(s) were seen "
                    "as scan-only/advice-only"
                )
                return []
            detail = installed.exception or installed.output.strip()
            self.warnings.append(
                "uv outdated listing is unsupported, and installed-tool fallback "
                f"failed: {detail[-500:]}"
            )
            return []
        if result.returncode != 0:
            raise RuntimeError(result.exception or result.output.strip())
        updates = self._items_from_outdated_output(result.output)
        if not updates and "latest:" not in result.output:
            installed = run_capture(["uv", "--color", "never", "tool", "list"], timeout=180)
            if installed.returncode not in {0, 1}:
                detail = installed.exception or installed.output.strip()
                self.warnings.append(f"uv installed-tool fallback failed: {detail[-500:]}")
        return updates

    def discover_all(self) -> list[UpdateItem]:
        result = run_capture(["uv", "--color", "never", "tool", "list"], timeout=180)
        if result.returncode != 0:
            raise RuntimeError(result.exception or result.output.strip())
        items: list[UpdateItem] = []
        for line in result.output.splitlines():
            stripped = line.strip()
            if not stripped or stripped.startswith("-") or stripped.startswith(" "):
                continue
            match = re.match(r"^(?P<name>[A-Za-z0-9_.@/+~-]+)\s+v?(?P<version>\S+)", stripped)
            if not match:
                continue
            package_id = match.group("name")
            current = match.group("version")
            if not valid_package_id(package_id):
                self.warnings.append(f"uv skipped unsafe tool name: {package_id!r}")
                continue
            items.append(
                inventory_only_item(
                    provider=self.key,
                    name=package_id,
                    package_id=package_id,
                    current=current,
                    source="uv tool",
                    instance=len(items),
                )
            )
        return items

    def _items_from_outdated_output(self, output: str) -> list[UpdateItem]:
        updates: list[UpdateItem] = []
        for line in output.splitlines():
            stripped = line.strip()
            if not stripped or stripped.startswith("-"):
                continue
            match = re.match(
                r"^(?P<name>[A-Za-z0-9_.@/+~-]+)\s+v?(?P<current>[^\s]+)"
                r"\s+\[latest:\s*v?(?P<latest>[^\]\s]+)\]",
                stripped,
            )
            if not match:
                if "git" in stripped.casefold() or "editable" in stripped.casefold():
                    self.warnings.append(
                        f"uv skipped manual-review tool source line: {stripped[:160]}"
                    )
                continue
            package_id = match.group("name")
            current = match.group("current")
            available = match.group("latest")
            if not valid_package_id(package_id):
                self.warnings.append(f"uv skipped unsafe tool name: {package_id!r}")
                continue
            if not valid_version(current) or not valid_version(available):
                self.warnings.append(f"uv skipped {package_id}: unsafe version text")
                continue
            updates.append(
                UpdateItem(
                    provider=self.key,
                    name=package_id,
                    package_id=package_id,
                    current=current,
                    available=available,
                    source="uv tool / PyPI",
                    scope="user",
                    requires_admin=False,
                    instance=len(updates),
                )
            )
        return updates

    def build_update_command(self, item: UpdateItem) -> list[str]:
        if item.scope != "user" or item.requires_admin:
            raise ValueError("uv tools may update only for the current user")
        if not valid_package_id(item.package_id):
            raise ValueError(f"unsafe uv tool name: {item.package_id!r}")
        return ["uv", "--color", "never", "tool", "upgrade", item.package_id]

    def build_uninstall_command(self, item: UpdateItem) -> list[str]:
        if item.scope != "user" or item.requires_admin:
            raise ValueError("uv tools may be removed only for the current user")
        if not valid_package_id(item.package_id):
            raise ValueError(f"unsafe uv tool name: {item.package_id!r}")
        return ["uv", "--color", "never", "tool", "uninstall", item.package_id]

    def result_warnings(self, result: CommandResult) -> list[str]:
        warnings = super().result_warnings(result)
        folded = result.output.casefold()
        if "nothing to upgrade" in folded:
            warnings.append("uv reported nothing to upgrade despite a prior outdated listing")
        modified_lines = [
            line.strip()
            for line in result.output.splitlines()
            if line.strip().casefold().startswith("modified ")
        ]
        if len(modified_lines) > 3:
            warnings.append(f"uv reported {len(modified_lines)} modified environment entries")
        elif modified_lines:
            warnings.append("uv modified environment entries: " + "; ".join(modified_lines))
        return warnings


class ChocolateyProvider(Provider):
    key = "chocolatey"
    label = "Chocolatey"
    executable = "choco"
    elevation_allowed = True
    success_codes = frozenset({0, 1641, 3010})
    reboot_codes = frozenset({1641, 3010})

    def discover(self) -> list[UpdateItem]:
        result = run_capture(["choco", "outdated", "--limit-output", "--no-progress"], timeout=900)
        if result.returncode not in {0, 2}:
            raise RuntimeError(result.exception or result.output.strip())
        updates: list[UpdateItem] = []
        for line in result.output.splitlines():
            fields = line.strip().split("|")
            if len(fields) < 3 or not valid_package_id(fields[0]):
                continue
            if not valid_version(fields[2]):
                self.warnings.append(
                    f"skipped {fields[0]}: unsafe Chocolatey version {fields[2]!r}"
                )
                continue
            updates.append(
                UpdateItem(
                    provider=self.key,
                    name=fields[0],
                    package_id=fields[0],
                    current=fields[1],
                    available=fields[2],
                    source="Chocolatey",
                    scope="machine",
                    requires_admin=True,
                )
            )
        return updates

    def discover_all(self) -> list[UpdateItem]:
        version = run_capture(["choco", "--version"], timeout=15)
        major = re.search(r"(?m)^\s*(\d+)\.\d+", version.output)
        if version.returncode != 0 or major is None:
            raise RuntimeError("Could not determine Chocolatey CLI version for local inventory")
        command = ["choco", "list", "--limit-output", "--no-progress"]
        if int(major.group(1)) < 2:
            command.append("--local-only")
        result = run_capture(
            command,
            timeout=600,
        )
        if result.returncode != 0:
            raise RuntimeError(result.exception or result.output.strip())
        items: list[UpdateItem] = []
        for line in result.output.splitlines():
            fields = line.strip().split("|")
            if len(fields) < 2 or not valid_package_id(fields[0]):
                continue
            items.append(
                inventory_only_item(
                    provider=self.key,
                    name=fields[0],
                    package_id=fields[0],
                    current=fields[1],
                    source="Chocolatey",
                    scope="machine",
                    requires_admin=True,
                    instance=len(items),
                )
            )
        return items

    def build_update_command(self, item: UpdateItem) -> list[str]:
        if not valid_version(item.available):
            raise ValueError(f"unsafe Chocolatey version string: {item.available!r}")
        return [
            "choco",
            "upgrade",
            item.package_id,
            "--version",
            item.available,
            "--yes",
            "--no-progress",
            "--verbose",
            "--fail-on-not-installed",
        ]

    def build_uninstall_command(self, item: UpdateItem) -> list[str]:
        if item.scope != "machine" or not item.requires_admin:
            raise ValueError("Chocolatey removals require a machine-scope administrator context")
        if not valid_package_id(item.package_id):
            raise ValueError(f"unsafe Chocolatey package id: {item.package_id!r}")
        return [
            "choco",
            "uninstall",
            item.package_id,
            "--yes",
            "--no-progress",
            "--verbose",
        ]


PSRESOURCE_JSON_BEGIN = "WinDevPilot_PSRESOURCE_JSON_BEGIN"
PSRESOURCE_JSON_END = "WinDevPilot_PSRESOURCE_JSON_END"
PSRESOURCE_DISCOVERY_SCRIPT = r"""
$ErrorActionPreference = 'Stop'
$ProgressPreference = 'SilentlyContinue'
$WarningPreference = 'SilentlyContinue'
$InformationPreference = 'SilentlyContinue'
$updateItems = [System.Collections.Generic.List[object]]::new()
$installedItems = [System.Collections.Generic.List[object]]::new()
$updateWarnings = [System.Collections.Generic.List[string]]::new()
$inventoryWarnings = [System.Collections.Generic.List[string]]::new()
$moduleVersion = $null
try {
    $module = Get-Module Microsoft.PowerShell.PSResourceGet -ListAvailable |
        Sort-Object -Property Version -Descending |
        Select-Object -First 1
    if ($null -eq $module) {
        throw 'Microsoft.PowerShell.PSResourceGet is not installed'
    }
    $moduleVersion = $module.Version.ToString()
    Import-Module Microsoft.PowerShell.PSResourceGet -MinimumVersion $module.Version
    $installed = @(
        Get-InstalledPSResource -Scope CurrentUser -ErrorAction SilentlyContinue 2>$null
    )
    foreach ($resource in $installed) {
        [void]$installedItems.Add([ordered]@{
            Name = [string]$resource.Name
            Version = $resource.Version.ToString()
            Repository = [string]$resource.Repository
            Type = $resource.Type.ToString()
            Location = [string]$resource.InstalledLocation
        })
    }
    if ($PSVersionTable.PSVersion -lt [version]'7.5') {
        [void]$updateWarnings.Add(
            'PowerShell 7.5 or later is required for data-only update arguments'
        )
    }
    else {
        $groups = @($installed | Group-Object -Property Name, Repository)
        foreach ($group in $groups) {
            $members = @($group.Group)
            $current = $members |
                Sort-Object -Property Version -Descending |
                Select-Object -First 1
            $name = [string]$current.Name
            $repository = [string]$current.Repository
            $resourceTypes = @(
                $members |
                    ForEach-Object { $_.Type.ToString() } |
                    Sort-Object -Unique
            )
            if ($resourceTypes.Count -ne 1) {
                [void]$updateWarnings.Add(
                    "$name ($repository) has ambiguous resource types; skipped"
                )
                continue
            }
            if ([string]::IsNullOrWhiteSpace($repository)) {
                [void]$updateWarnings.Add(
                    "$name has no registered repository; skipped rather than guessed"
                )
                continue
            }
            try {
                $findParameters = @{
                    Name = $name
                    Repository = $repository
                    ErrorAction = 'Stop'
                }
                $currentVersion = $current.Version.ToString()
                if ($currentVersion.Contains('-')) {
                    $findParameters.Prerelease = $true
                }
                $latest = Find-PSResource @findParameters |
                    Sort-Object -Property Version -Descending |
                    Select-Object -First 1
                if ($null -ne $latest -and $latest.Version -gt $current.Version) {
                    $installedVersions = @(
                        $members |
                            Sort-Object -Property Version -Descending |
                            ForEach-Object { $_.Version.ToString() }
                    )
                    [void]$updateItems.Add([ordered]@{
                        Name = $name
                        Current = $currentVersion
                        Available = $latest.Version.ToString()
                        Repository = $repository
                        Type = $resourceTypes[0]
                        InstalledLocation = [string]$current.InstalledLocation
                        InstalledVersions = $installedVersions
                    })
                }
            }
            catch {
                [void]$updateWarnings.Add(
                    "$name ($repository): $($_.Exception.Message)"
                )
            }
        }
    }
}
catch {
    [void]$updateWarnings.Add($_.Exception.Message)
    [void]$inventoryWarnings.Add($_.Exception.Message)
}
$payload = [ordered]@{
    Schema = 2
    Updates = [ordered]@{
        Schema = 1
        Items = @($updateItems)
        Warnings = @($updateWarnings)
        PSVersion = $PSVersionTable.PSVersion.ToString()
        PSResourceGet = $moduleVersion
    }
    Installed = [ordered]@{
        Schema = 1
        Items = @($installedItems)
        Warnings = @($inventoryWarnings)
    }
}
[Console]::Out.WriteLine('WinDevPilot_PSRESOURCE_JSON_BEGIN')
[Console]::Out.WriteLine(($payload | ConvertTo-Json -Depth 8 -Compress))
[Console]::Out.WriteLine('WinDevPilot_PSRESOURCE_JSON_END')
""".strip()
PSRESOURCE_UPDATE_SCRIPT = r"""
$ErrorActionPreference = 'Stop'
$ProgressPreference = 'SilentlyContinue'
if ($args.Count -ne 3) {
    throw 'WinDevPilot requires resource name, version, and repository arguments'
}
$name = [string]$args[0]
$version = [string]$args[1]
$repository = [string]$args[2]
$updateParameters = @{
    Name = $name
    Version = $version
    Repository = $repository
    Scope = 'CurrentUser'
    TrustRepository = $true
    AcceptLicense = $true
    Quiet = $true
    Confirm = $false
    ErrorAction = 'Stop'
    Verbose = $true
}
if ($version.Contains('-')) {
    $updateParameters.Prerelease = $true
}
Update-PSResource @updateParameters
""".strip()
PSRESOURCE_VERSION_SCRIPT = r"""
$module = Get-Module Microsoft.PowerShell.PSResourceGet -ListAvailable |
    Sort-Object -Property Version -Descending |
    Select-Object -First 1
[ordered]@{
    PowerShell = $PSVersionTable.PSVersion.ToString()
    PSResourceGet = if ($null -eq $module) { $null } else { $module.Version.ToString() }
} | ConvertTo-Json -Compress
""".strip()


PS5_MODULE_JSON_BEGIN = "WinDevPilot_PS5MODULE_JSON_BEGIN"
PS5_MODULE_JSON_END = "WinDevPilot_PS5MODULE_JSON_END"
PS5_MODULE_DISCOVERY_SCRIPT = r"""
$ErrorActionPreference = 'Stop'
$ProgressPreference = 'SilentlyContinue'
$WarningPreference = 'SilentlyContinue'
$updateItems = [System.Collections.Generic.List[object]]::new()
$installedItems = [System.Collections.Generic.List[object]]::new()
$updateWarnings = [System.Collections.Generic.List[string]]::new()
$inventoryWarnings = [System.Collections.Generic.List[string]]::new()
try {
    $ps5ModuleRoots = @(
        (Join-Path ([Environment]::GetFolderPath('MyDocuments')) 'WindowsPowerShell\Modules'),
        (Join-Path $env:USERPROFILE 'Documents\WindowsPowerShell\Modules'),
        (Join-Path $env:ProgramFiles 'WindowsPowerShell\Modules'),
        (Join-Path $env:WINDIR 'System32\WindowsPowerShell\v1.0\Modules')
    ) | Where-Object { -not [string]::IsNullOrWhiteSpace($_) -and (Test-Path $_) }
    $env:PSModulePath = ($ps5ModuleRoots | Select-Object -Unique) -join [System.IO.Path]::PathSeparator
    Import-Module PowerShellGet -ErrorAction Stop
    $currentUserRoots = @(
        (Join-Path ([Environment]::GetFolderPath('MyDocuments')) 'WindowsPowerShell\Modules'),
        (Join-Path $env:USERPROFILE 'Documents\WindowsPowerShell\Modules')
    ) | Where-Object { -not [string]::IsNullOrWhiteSpace($_) } | Select-Object -Unique
    $installed = @(Get-InstalledModule -ErrorAction SilentlyContinue)
    $allUsersCount = 0
    foreach ($module in $installed) {
        $name = [string]$module.Name
        $repository = [string]$module.Repository
        $location = [string]$module.InstalledLocation
        $isCurrentUser = $false
        foreach ($root in $currentUserRoots) {
            if (-not [string]::IsNullOrWhiteSpace($root) -and
                $location.StartsWith($root, [System.StringComparison]::OrdinalIgnoreCase)) {
                $isCurrentUser = $true
            }
        }
        if (-not $isCurrentUser) {
            $allUsersCount += 1
            [void]$inventoryWarnings.Add(
                "$name is installed outside CurrentUser and was not listed"
            )
            continue
        }
        [void]$installedItems.Add([ordered]@{
            Name = $name
            Version = $module.Version.ToString()
            Repository = $repository
            Location = $location
        })
        if ([string]::IsNullOrWhiteSpace($repository)) {
            [void]$updateWarnings.Add("$name has no registered repository; skipped")
            continue
        }
        try {
            $latest = Find-Module -Name $name -Repository $repository -ErrorAction Stop |
                Sort-Object -Property Version -Descending |
                Select-Object -First 1
            if ($null -ne $latest -and $latest.Version -gt $module.Version) {
                [void]$updateItems.Add([ordered]@{
                    Name = $name
                    Current = $module.Version.ToString()
                    Available = $latest.Version.ToString()
                    Repository = $repository
                    InstalledLocation = $location
                })
            }
        }
        catch {
            [void]$updateWarnings.Add("$name ($repository): $($_.Exception.Message)")
        }
    }
    if ($allUsersCount -gt 0) {
        [void]$updateWarnings.Add(
            "$allUsersCount Windows PowerShell module(s) installed outside CurrentUser were skipped"
        )
    }
}
catch {
    [void]$updateWarnings.Add($_.Exception.Message)
    [void]$inventoryWarnings.Add($_.Exception.Message)
}
$payload = [ordered]@{
    Schema = 2
    Updates = [ordered]@{
        Schema = 1
        Items = @($updateItems)
        Warnings = @($updateWarnings)
        PSVersion = $PSVersionTable.PSVersion.ToString()
    }
    Installed = [ordered]@{
        Schema = 1
        Items = @($installedItems)
        Warnings = @($inventoryWarnings)
    }
}
[Console]::Out.WriteLine('WinDevPilot_PS5MODULE_JSON_BEGIN')
[Console]::Out.WriteLine(($payload | ConvertTo-Json -Depth 7 -Compress))
[Console]::Out.WriteLine('WinDevPilot_PS5MODULE_JSON_END')
""".strip()
PS5_MODULE_UPDATE_SCRIPT = r"""
$ErrorActionPreference = 'Stop'
$ProgressPreference = 'SilentlyContinue'
$name = '{NAME}'
$version = '{VERSION}'
$repository = '{REPOSITORY}'
$ps5ModuleRoots = @(
    (Join-Path ([Environment]::GetFolderPath('MyDocuments')) 'WindowsPowerShell\Modules'),
    (Join-Path $env:USERPROFILE 'Documents\WindowsPowerShell\Modules'),
    (Join-Path $env:ProgramFiles 'WindowsPowerShell\Modules'),
    (Join-Path $env:WINDIR 'System32\WindowsPowerShell\v1.0\Modules')
) | Where-Object { -not [string]::IsNullOrWhiteSpace($_) -and (Test-Path $_) }
$env:PSModulePath = ($ps5ModuleRoots | Select-Object -Unique) -join [System.IO.Path]::PathSeparator
Import-Module PowerShellGet -ErrorAction Stop
$installCommand = Get-Command PowerShellGet\Install-Module -ErrorAction Stop
$parameters = @{
    Name = $name
    RequiredVersion = $version
    Repository = $repository
    Scope = 'CurrentUser'
    Force = $true
    AllowClobber = $true
    Confirm = $false
    Verbose = $true
}
if ($installCommand.Parameters.ContainsKey('AcceptLicense')) {
    $parameters['AcceptLicense'] = $true
}
& $installCommand @parameters
""".strip()


def require_powershell_single_quoted_literals(*values: str) -> None:
    """Reject data that could leave a fixed PowerShell single-quoted literal."""

    if any("'" in value or "\r" in value or "\n" in value for value in values):
        raise ValueError("PowerShell literal contains a quote or newline")


def render_ps5_module_update_script(name: str, version: str, repository: str) -> str:
    if not valid_package_id(name):
        raise ValueError(f"unsafe Windows PowerShell module name: {name!r}")
    if not valid_version(version):
        raise ValueError(f"unsafe Windows PowerShell module version: {version!r}")
    if not valid_provider_source(repository):
        raise ValueError(f"unsafe PowerShell repository name: {repository!r}")
    require_powershell_single_quoted_literals(name, version, repository)
    return (
        PS5_MODULE_UPDATE_SCRIPT.replace("{NAME}", name)
        .replace("{VERSION}", version)
        .replace("{REPOSITORY}", repository)
    )


def render_ps5_module_uninstall_script(name: str, version: str) -> str:
    if not valid_package_id(name):
        raise ValueError(f"unsafe Windows PowerShell module name: {name!r}")
    if not valid_version(version):
        raise ValueError(f"unsafe Windows PowerShell module version: {version!r}")
    require_powershell_single_quoted_literals(name, version)
    return (
        "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue'; "
        "Import-Module PowerShellGet -ErrorAction Stop; "
        f"Uninstall-Module -Name '{name}' -RequiredVersion '{version}' "
        "-Force -Confirm:$false -ErrorAction Stop"
    )


def split_combined_powershell_payload(
    payload: Any,
    provider_label: str,
) -> tuple[dict[str, Any], dict[str, Any]]:
    """Validate a one-process PowerShell update-and-inventory snapshot."""

    if not isinstance(payload, dict) or payload.get("Schema") != 2:
        raise ValueError(f"{provider_label} returned an unsupported combined JSON payload")
    updates = payload.get("Updates")
    installed = payload.get("Installed")
    if not isinstance(updates, dict) or not isinstance(installed, dict):
        raise ValueError(f"{provider_label} combined JSON payload is incomplete")
    return updates, installed


class _CombinedPowerShellProvider(Provider):
    """Share one installed-resource snapshot between a scan's two provider phases."""

    def __init__(self) -> None:
        super().__init__()
        self._combined_inventory_payload: dict[str, Any] | None = None

    def _start_combined_discovery(self) -> None:
        # A failed or interrupted update phase must never expose a prior scan's inventory.
        self._combined_inventory_payload = None

    def _cache_combined_inventory(self, payload: Any) -> dict[str, Any]:
        updates, installed = split_combined_powershell_payload(payload, self.label)
        self._combined_inventory_payload = installed
        return updates

    def _take_combined_inventory(self) -> dict[str, Any] | None:
        payload = self._combined_inventory_payload
        self._combined_inventory_payload = None
        return payload


class WindowsPowerShellProvider(_CombinedPowerShellProvider):
    key = "powershell5"
    label = "Windows PowerShell 5.x modules (CurrentUser)"
    executable = "powershell"

    def version_command(self) -> list[str]:
        return [
            "powershell",
            "-NoLogo",
            "-NoProfile",
            "-NonInteractive",
            "-Command",
            "$PSVersionTable.PSVersion.ToString()",
        ]

    def discover(self) -> list[UpdateItem]:
        self._start_combined_discovery()
        result = run_capture(
            [
                "powershell",
                "-NoLogo",
                "-NoProfile",
                "-NonInteractive",
                "-Command",
                PS5_MODULE_DISCOVERY_SCRIPT,
            ],
            timeout=POWERSHELL_DISCOVERY_TIMEOUT_SECONDS,
        )
        if result.returncode != 0:
            raise RuntimeError(result.exception or result.output.strip())
        payload = sentinel_json_payload(result.output, PS5_MODULE_JSON_BEGIN, PS5_MODULE_JSON_END)
        return self._items_from_payload(self._cache_combined_inventory(payload))

    def discover_all(self) -> list[UpdateItem]:
        cached_payload = self._take_combined_inventory()
        if cached_payload is not None:
            return self._installed_items_from_payload(cached_payload)
        script = f"""
$ErrorActionPreference = 'Stop'
$ProgressPreference = 'SilentlyContinue'
$WarningPreference = 'SilentlyContinue'
$items = @()
$warnings = @()
try {{
    Import-Module PowerShellGet -ErrorAction Stop
    $currentUserRoots = @(
        (Join-Path ([Environment]::GetFolderPath('MyDocuments')) 'WindowsPowerShell\\Modules'),
        (Join-Path $env:USERPROFILE 'Documents\\WindowsPowerShell\\Modules')
    ) | Where-Object {{ -not [string]::IsNullOrWhiteSpace($_) }} | Select-Object -Unique
    foreach ($module in @(Get-InstalledModule -ErrorAction SilentlyContinue)) {{
        $location = [string]$module.InstalledLocation
        $isCurrentUser = $false
        foreach ($root in $currentUserRoots) {{
            if ($location.StartsWith($root, [System.StringComparison]::OrdinalIgnoreCase)) {{
                $isCurrentUser = $true
            }}
        }}
        if ($isCurrentUser) {{
            $items += [ordered]@{{
                Name = [string]$module.Name
                Version = $module.Version.ToString()
                Repository = [string]$module.Repository
                Location = $location
            }}
        }} else {{
            $warnings += "$($module.Name) is installed outside CurrentUser and was not listed"
        }}
    }}
}} catch {{
    $warnings += $_.Exception.Message
}}
$payload = [ordered]@{{ Schema = 1; Items = @($items); Warnings = @($warnings) }}
[Console]::Out.WriteLine('{PS5_MODULE_JSON_BEGIN}')
[Console]::Out.WriteLine(($payload | ConvertTo-Json -Depth 5 -Compress))
[Console]::Out.WriteLine('{PS5_MODULE_JSON_END}')
""".strip()
        result = run_capture(
            ["powershell", "-NoLogo", "-NoProfile", "-NonInteractive", "-Command", script],
            timeout=POWERSHELL_DISCOVERY_TIMEOUT_SECONDS,
        )
        if result.returncode != 0:
            raise RuntimeError(result.exception or result.output.strip())
        payload = sentinel_json_payload(result.output, PS5_MODULE_JSON_BEGIN, PS5_MODULE_JSON_END)
        return self._installed_items_from_payload(payload)

    def _installed_items_from_payload(self, payload: Any) -> list[UpdateItem]:
        if not isinstance(payload, dict) or payload.get("Schema") != 1:
            raise ValueError("PowerShellGet installed inventory returned unsupported JSON")
        raw_warnings = payload.get("Warnings", [])
        if isinstance(raw_warnings, list):
            self.warnings.extend(str(warning) for warning in raw_warnings if warning)
        raw_items = payload.get("Items", [])
        if not isinstance(raw_items, list):
            return []
        items: list[UpdateItem] = []
        for entry in raw_items:
            if not isinstance(entry, dict):
                continue
            package_id = str(entry.get("Name", ""))
            current = str(entry.get("Version", ""))
            repository = str(entry.get("Repository", "")) or "PowerShellGet"
            if not valid_package_id(package_id):
                self.warnings.append(f"skipped unsafe Windows PowerShell module: {package_id!r}")
                continue
            items.append(
                inventory_only_item(
                    provider=self.key,
                    name=package_id,
                    package_id=package_id,
                    current=current,
                    source=repository,
                    instance=len(items),
                )
            )
        return items

    def _items_from_payload(self, payload: Any) -> list[UpdateItem]:
        if not isinstance(payload, dict) or payload.get("Schema") != 1:
            raise ValueError("PowerShellGet returned an unsupported JSON payload")
        raw_warnings = payload.get("Warnings", [])
        if isinstance(raw_warnings, list):
            self.warnings.extend(str(warning) for warning in raw_warnings if warning)
        raw_items = payload.get("Items", [])
        if not isinstance(raw_items, list):
            raise ValueError("PowerShellGet items are not a list")
        updates: list[UpdateItem] = []
        for instance, entry in enumerate(raw_items):
            if not isinstance(entry, dict):
                self.warnings.append("skipped malformed Windows PowerShell module entry")
                continue
            package_id = str(entry.get("Name", ""))
            current = str(entry.get("Current", ""))
            available = str(entry.get("Available", ""))
            repository = str(entry.get("Repository", ""))
            if not valid_package_id(package_id):
                self.warnings.append(f"skipped unsafe Windows PowerShell module: {package_id!r}")
                continue
            if not valid_version(current) or not valid_version(available):
                self.warnings.append(f"skipped {package_id}: unsafe PowerShellGet version data")
                continue
            if not valid_provider_source(repository):
                self.warnings.append(f"skipped {package_id}: unsafe repository {repository!r}")
                continue
            updates.append(
                UpdateItem(
                    provider=self.key,
                    name=package_id,
                    package_id=package_id,
                    current=current,
                    available=available,
                    source=repository,
                    scope="user",
                    requires_admin=False,
                    instance=instance,
                )
            )
        return updates

    def build_update_command(self, item: UpdateItem) -> list[str]:
        if item.scope != "user" or item.requires_admin:
            raise ValueError("Windows PowerShell modules may update only in CurrentUser scope")
        if not valid_version(item.available):
            raise ValueError(f"unsafe Windows PowerShell module version: {item.available!r}")
        if not valid_provider_source(item.source):
            raise ValueError(f"unsafe PowerShell repository name: {item.source!r}")
        return [
            "powershell",
            "-NoLogo",
            "-NoProfile",
            "-NonInteractive",
            "-Command",
            render_ps5_module_update_script(item.package_id, item.available, item.source),
        ]

    def build_uninstall_command(self, item: UpdateItem) -> list[str]:
        if item.scope != "user" or item.requires_admin:
            raise ValueError("Windows PowerShell modules may be removed only in CurrentUser scope")
        if not valid_package_id(item.package_id) or not valid_version(item.current):
            raise ValueError("unsafe Windows PowerShell module identity or version")
        return [
            "powershell",
            "-NoLogo",
            "-NoProfile",
            "-NonInteractive",
            "-Command",
            render_ps5_module_uninstall_script(item.package_id, item.current),
        ]


class PowerShellProvider(_CombinedPowerShellProvider):
    key = "powershell"
    label = "PowerShell resources (CurrentUser)"
    executable = "pwsh"

    def version_command(self) -> list[str]:
        return [
            "pwsh",
            "-NoLogo",
            "-NoProfile",
            "-NonInteractive",
            "-Command",
            PSRESOURCE_VERSION_SCRIPT,
        ]

    def discover(self) -> list[UpdateItem]:
        self._start_combined_discovery()
        result = run_capture(
            [
                "pwsh",
                "-NoLogo",
                "-NoProfile",
                "-NonInteractive",
                "-Command",
                PSRESOURCE_DISCOVERY_SCRIPT,
            ],
            timeout=POWERSHELL_DISCOVERY_TIMEOUT_SECONDS,
        )
        if result.returncode != 0:
            raise RuntimeError(result.exception or result.output.strip())
        payload = sentinel_json_payload(result.output, PSRESOURCE_JSON_BEGIN, PSRESOURCE_JSON_END)
        return self._items_from_payload(self._cache_combined_inventory(payload))

    def discover_all(self) -> list[UpdateItem]:
        cached_payload = self._take_combined_inventory()
        if cached_payload is not None:
            return self._installed_items_from_payload(cached_payload)
        script = f"""
$ErrorActionPreference = 'Stop'
$ProgressPreference = 'SilentlyContinue'
$WarningPreference = 'SilentlyContinue'
$items = @()
$warnings = @()
try {{
    Import-Module Microsoft.PowerShell.PSResourceGet -ErrorAction Stop
    foreach ($resource in @(Get-InstalledPSResource -Scope CurrentUser -ErrorAction SilentlyContinue)) {{
        $items += [ordered]@{{
            Name = [string]$resource.Name
            Version = $resource.Version.ToString()
            Repository = [string]$resource.Repository
            Type = $resource.Type.ToString()
            Location = [string]$resource.InstalledLocation
        }}
    }}
}} catch {{
    $warnings += $_.Exception.Message
}}
$payload = [ordered]@{{ Schema = 1; Items = @($items); Warnings = @($warnings) }}
[Console]::Out.WriteLine('{PSRESOURCE_JSON_BEGIN}')
[Console]::Out.WriteLine(($payload | ConvertTo-Json -Depth 5 -Compress))
[Console]::Out.WriteLine('{PSRESOURCE_JSON_END}')
""".strip()
        result = run_capture(
            ["pwsh", "-NoLogo", "-NoProfile", "-NonInteractive", "-Command", script],
            timeout=600,
        )
        if result.returncode != 0:
            raise RuntimeError(result.exception or result.output.strip())
        payload = sentinel_json_payload(result.output, PSRESOURCE_JSON_BEGIN, PSRESOURCE_JSON_END)
        return self._installed_items_from_payload(payload)

    def _installed_items_from_payload(self, payload: Any) -> list[UpdateItem]:
        if not isinstance(payload, dict) or payload.get("Schema") != 1:
            raise ValueError("PSResourceGet installed inventory returned unsupported JSON")
        raw_warnings = payload.get("Warnings", [])
        if isinstance(raw_warnings, list):
            self.warnings.extend(str(warning) for warning in raw_warnings if warning)
        raw_items = payload.get("Items", [])
        if not isinstance(raw_items, list):
            return []
        items: list[UpdateItem] = []
        for entry in raw_items:
            if not isinstance(entry, dict):
                continue
            package_id = str(entry.get("Name", ""))
            current = str(entry.get("Version", ""))
            repository = str(entry.get("Repository", "")) or "PSResourceGet"
            if not valid_package_id(package_id):
                self.warnings.append(f"skipped unsafe PowerShell resource name: {package_id!r}")
                continue
            items.append(
                inventory_only_item(
                    provider=self.key,
                    name=package_id,
                    package_id=package_id,
                    current=current,
                    source=repository,
                    instance=len(items),
                )
            )
        return items

    def _items_from_payload(self, payload: Any) -> list[UpdateItem]:
        if not isinstance(payload, dict) or payload.get("Schema") != 1:
            raise ValueError("PSResourceGet returned an unsupported JSON payload")
        raw_warnings = payload.get("Warnings", [])
        if not isinstance(raw_warnings, list):
            raise ValueError("PSResourceGet warnings are not a list")
        self.warnings.extend(str(warning) for warning in raw_warnings if warning)
        raw_items = payload.get("Items", [])
        if not isinstance(raw_items, list):
            raise ValueError("PSResourceGet items are not a list")
        updates: list[UpdateItem] = []
        counts: dict[tuple[str, str], int] = {}
        for entry in raw_items:
            if not isinstance(entry, dict):
                self.warnings.append("skipped malformed PSResourceGet update entry")
                continue
            package_id = str(entry.get("Name", ""))
            current = str(entry.get("Current", ""))
            available = str(entry.get("Available", ""))
            repository = str(entry.get("Repository", ""))
            if not valid_package_id(package_id):
                self.warnings.append(f"skipped unsafe PowerShell resource name: {package_id!r}")
                continue
            if not valid_version(current) or not valid_version(available):
                self.warnings.append(f"skipped {package_id}: unsafe PSResourceGet version data")
                continue
            if not valid_provider_source(repository):
                self.warnings.append(f"skipped {package_id}: unsafe repository name {repository!r}")
                continue
            installed_versions = entry.get("InstalledVersions", [])
            if isinstance(installed_versions, list) and len(installed_versions) > 1:
                self.warnings.append(
                    f"{package_id} has {len(installed_versions)} CurrentUser versions; "
                    f"showing newest installed version {current}"
                )
            identity = (package_id.casefold(), repository.casefold())
            instance = counts.get(identity, 0)
            counts[identity] = instance + 1
            updates.append(
                UpdateItem(
                    provider=self.key,
                    name=package_id,
                    package_id=package_id,
                    current=current,
                    available=available,
                    source=repository,
                    scope="user",
                    instance=instance,
                )
            )
        return updates

    def build_update_command(self, item: UpdateItem) -> list[str]:
        if item.scope != "user" or item.requires_admin:
            raise ValueError("PowerShell resources may update only in CurrentUser scope")
        if not valid_version(item.available):
            raise ValueError(f"unsafe PowerShell resource version: {item.available!r}")
        if not valid_provider_source(item.source):
            raise ValueError(f"unsafe PowerShell repository name: {item.source!r}")
        return [
            "pwsh",
            "-NoLogo",
            "-NoProfile",
            "-NonInteractive",
            "-CommandWithArgs",
            PSRESOURCE_UPDATE_SCRIPT,
            item.package_id,
            item.available,
            item.source,
        ]

    def build_uninstall_command(self, item: UpdateItem) -> list[str]:
        if item.scope != "user" or item.requires_admin:
            raise ValueError("PowerShell resources may be removed only in CurrentUser scope")
        if not valid_package_id(item.package_id) or not valid_version(item.current):
            raise ValueError("unsafe PowerShell resource identity or version")
        script = (
            "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue'; "
            "$name = [string]$args[0]; $version = [string]$args[1]; "
            "Import-Module Microsoft.PowerShell.PSResourceGet -ErrorAction Stop; "
            "Uninstall-PSResource -Name $name -Version $version -Scope CurrentUser "
            "-Confirm:$false -ErrorAction Stop"
        )
        return [
            "pwsh",
            "-NoLogo",
            "-NoProfile",
            "-NonInteractive",
            "-CommandWithArgs",
            script,
            item.package_id,
            item.current,
        ]


class PortableProvider(Provider):
    key = PORTABLE_PROVIDER_KEY
    label = "WinDevPilot · Portables"
    default_enabled = False
    configurable = False

    def available(self) -> bool:
        return True

    def discover(self) -> list[UpdateItem]:
        return []

    def discover_all(self) -> list[UpdateItem]:
        return []

    def build_update_command(self, item: UpdateItem) -> list[str]:
        raise ValueError("portable updates are detection-only in this release")

    def build_uninstall_command(self, item: UpdateItem) -> list[str]:
        raise ValueError("portable apps do not have a proven package-manager uninstall route")


PROVIDER_TYPES: tuple[type[Provider], ...] = (
    WingetProvider,
    MicrosoftStoreProvider,
    NpmProvider,
    BunProvider,
    ScoopProvider,
    CargoProvider,
    VcpkgProvider,
    RustupProvider,
    PipProvider,
    PipxProvider,
    DotNetToolProvider,
    UvToolProvider,
    ChocolateyProvider,
    WindowsPowerShellProvider,
    PowerShellProvider,
)

def build_providers(*, debug_mode: bool = False) -> dict[str, Provider]:
    providers = [provider_type() for provider_type in PROVIDER_TYPES]
    providers.append(PortableProvider())
    for provider in providers:
        provider.debug_mode = debug_mode
    return {provider.key: provider for provider in providers}


def material_unavailable_provider_keys(
    providers: Mapping[str, Provider],
    enabled: Mapping[str, bool],
    availability: Mapping[str, bool] | None = None,
) -> set[str]:
    """Flag missing core coverage and known-installed managers, not absent optional tools."""

    known_executables = known_windows_tool_executable_paths()
    material: set[str] = set()
    for key, provider in providers.items():
        if not enabled.get(key, provider.default_enabled):
            continue
        available = (
            bool(availability.get(key))
            if availability is not None
            else provider.available()
        )
        if available:
            continue
        executable = provider.executable.casefold()
        if key == "winget" or (executable and executable in known_executables):
            material.add(key)
    return material


def duration_prioritized_providers(
    providers: Sequence[Provider],
    duration_hints: Mapping[str, float],
) -> list[tuple[int, Provider]]:
    """Schedule likely-long providers first while retaining canonical result indices."""

    canonical = list(enumerate(providers))
    return sorted(
        canonical,
        key=lambda entry: (-duration_hints.get(entry[1].key, 0.0), entry[0]),
    )


def recent_untouched_provider_snapshot_ages(
    provider_keys: Iterable[str],
    attempted_provider_keys: Set[str],
    refreshed_at: Mapping[str, float],
    *,
    now: float,
    grace_seconds: float = POST_UPDATE_PROVIDER_REUSE_GRACE_SECONDS,
) -> dict[str, float]:
    """Return recent untouched snapshots safe to retain during automatic verification."""

    active_keys = {str(key) for key in provider_keys if str(key)}
    attempted = {str(key) for key in attempted_provider_keys if str(key)}
    reusable: dict[str, float] = {}
    if grace_seconds <= 0:
        return reusable
    for key in active_keys - attempted:
        try:
            observed_at = float(refreshed_at[key])
        except (KeyError, TypeError, ValueError):
            continue
        age = max(0.0, now - observed_at)
        if age < grace_seconds:
            reusable[key] = age

    # WinGet and Store inventory overlap. They must either retain the same
    # observation generation or refresh together; mixing one recent snapshot
    # with one fresh provider result can temporarily invent duplicate identities.
    joint_keys = active_keys.intersection(
        {WingetProvider.key, MICROSOFT_STORE_PROVIDER_KEY}
    )
    if joint_keys and not joint_keys.issubset(reusable):
        for key in joint_keys:
            reusable.pop(key, None)
    return reusable


TOOLCHAIN_PROBES: tuple[tuple[str, str, tuple[str, ...]], ...] = (
    ("Git", "source control command-line client", ("git", "--version")),
    ("WinGet", "Windows package manager CLI", ("winget", "--version")),
    (".NET SDK", ".NET SDK and global-tool host", ("dotnet", "--version")),
    ("Node.js", "JavaScript runtime", ("node", "--version")),
    ("npm", "Node package manager and global package CLI", ("npm", "--version")),
    ("Bun", "JavaScript runtime, bundler, and package manager", ("bun", "--version")),
    ("Corepack", "Node package-manager shim for pnpm/yarn", ("corepack", "--version")),
    ("pnpm", "fast Node package manager", ("pnpm", "--version")),
    ("Yarn", "Node package manager", ("yarn", "--version")),
    ("Python Launcher", "Windows py launcher", ("py", "--version")),
    ("Python installs", "Python versions registered with py launcher", ("py", "-0p")),
    ("Python", "default python on PATH", ("python", "--version")),
    ("uv", "fast Python package/project/tool manager", ("uv", "--version")),
    (
        "pipx",
        "optional isolated Python CLI app manager; uv offers the same core workflow",
        ("pipx", "--version"),
    ),
    ("rustup", "Rust toolchain manager", ("rustup", "--version")),
    ("Cargo", "Rust package/build tool", ("cargo", "--version")),
    ("vcpkg", "C/C++ package manager for native libraries", ("vcpkg", "--version")),
    (
        "Windows PowerShell 5.x",
        "legacy Windows PowerShell module host",
        (
            "powershell",
            "-NoLogo",
            "-NoProfile",
            "-NonInteractive",
            "-Command",
            "$PSVersionTable.PSVersion.ToString()",
        ),
    ),
    (
        "PowerShell 7.x",
        "modern PowerShell module/resource host",
        (
            "pwsh",
            "-NoLogo",
            "-NoProfile",
            "-NonInteractive",
            "-Command",
            "$PSVersionTable.PSVersion.ToString()",
        ),
    ),
    ("Go", "Go compiler/toolchain", ("go", "version")),
    ("CMake", "cross-platform native build generator", ("cmake", "--version")),
    ("Ninja", "fast native build executor", ("ninja", "--version")),
    ("Visual Studio Code", "VS Code command-line launcher", ("code", "--version")),
)


# ==================== Application settings ====================

class SettingsStore:
    def __init__(self, path: Path | None = None) -> None:
        self.path = path or (app_data_dir() / "settings.json")
        self.data = self._defaults()
        self.recovered_corrupt_settings: Path | None = None
        self.migrated_permission_hold_count = 0
        self.load()

    @staticmethod
    def _defaults() -> dict[str, Any]:
        return {
            "schema": SETTINGS_SCHEMA_VERSION,
            "providers": {
                provider_type.key: provider_type.default_enabled for provider_type in PROVIDER_TYPES
            },
            "ignored": [],
            "attempt_holds": {},
            "restart_pending": {},
            "applicability_history": {},
            "package_history": {},
            "auto_elevate": True,
            "window_geometry": "1280x820",
            "window_geometry_dpi": 0,
            "preserve_settings": False,
            "view_preferences": {},
            "provider_duration_hints": {},
        }

    def load(self) -> None:
        if not self.path.exists():
            return
        try:
            loaded = json.loads(self.path.read_text(encoding="utf-8"))
            if not isinstance(loaded, dict):
                self.recovered_corrupt_settings = self._quarantine_corrupt_file(
                    suffix="invalid-root"
                )
                return
            schema = loaded.get("schema", SETTINGS_SCHEMA_VERSION)
            if schema != SETTINGS_SCHEMA_VERSION:
                self.recovered_corrupt_settings = self._quarantine_corrupt_file(
                    suffix=f"unsupported-schema-{schema}"
                )
                return
            defaults = self._defaults()
            providers = defaults["providers"]
            if isinstance(loaded.get("providers"), dict):
                invalid_provider_values = [
                    key
                    for key, value in loaded["providers"].items()
                    if key in providers and not isinstance(value, bool)
                ]
                if invalid_provider_values:
                    self.recovered_corrupt_settings = self._quarantine_corrupt_file(
                        suffix="invalid-provider-values"
                    )
                    return
                providers.update(
                    {
                        str(key): value
                        for key, value in loaded["providers"].items()
                        if key in providers
                    }
                )
            if "auto_elevate" in loaded and not isinstance(loaded["auto_elevate"], bool):
                self.recovered_corrupt_settings = self._quarantine_corrupt_file(
                    suffix="invalid-auto-elevate"
                )
                return
            duration_hints = loaded.get("provider_duration_hints", {})
            if isinstance(duration_hints, dict):
                defaults["provider_duration_hints"] = {
                    str(key): float(value)
                    for key, value in duration_hints.items()
                    if key in providers
                    and isinstance(value, (int, float))
                    and not isinstance(value, bool)
                    and math.isfinite(float(value))
                    and 0.0 <= float(value) <= 600.0
                }
            self.data = defaults | {
                key: value
                for key, value in loaded.items()
                if key
                in {
                    "ignored",
                    "attempt_holds",
                    "restart_pending",
                    "applicability_history",
                    "package_history",
                    "auto_elevate",
                    "schema",
                    "window_geometry",
                    "window_geometry_dpi",
                }
            }
            self.data["providers"] = providers
            self.data["preserve_settings"] = loaded.get("preserve_settings") is True
            preferences = loaded.get("view_preferences")
            self.data["view_preferences"] = preferences if isinstance(preferences, dict) else {}
            ignored = self.data.get("ignored")
            self.data["ignored"] = (
                [value for value in ignored if isinstance(value, str)]
                if isinstance(ignored, list)
                else []
            )
            geometry = str(self.data.get("window_geometry", "")).strip()
            if not GEOMETRY_RE.fullmatch(geometry):
                self.data["window_geometry"] = "1280x820"
            try:
                stored_dpi = int(self.data.get("window_geometry_dpi", 0))
            except (TypeError, ValueError):
                stored_dpi = 0
            self.data["window_geometry_dpi"] = stored_dpi if 48 <= stored_dpi <= 480 else 0
            holds = self.data.get("attempt_holds")
            if not isinstance(holds, dict):
                self.data["attempt_holds"] = {}
            else:
                self.data["attempt_holds"] = {
                    str(key): value
                    for key, value in holds.items()
                    if isinstance(key, str) and SHA256_RE.fullmatch(key) and isinstance(value, dict)
                }
            restart_pending = self.data.get("restart_pending")
            if not isinstance(restart_pending, dict):
                self.data["restart_pending"] = {}
            else:
                self.data["restart_pending"] = {
                    str(key): value
                    for key, value in restart_pending.items()
                    if isinstance(key, str)
                    and SHA256_RE.fullmatch(key)
                    and isinstance(value, dict)
                }
            history = self.data.get("applicability_history")
            if not isinstance(history, dict):
                self.data["applicability_history"] = {}
            else:
                self.data["applicability_history"] = {
                    str(key): value
                    for key, value in history.items()
                    if isinstance(key, str)
                    and SHA256_RE.fullmatch(key)
                    and isinstance(value, dict)
                }
            package_history = self.data.get("package_history")
            if not isinstance(package_history, dict):
                self.data["package_history"] = {}
            else:
                self.data["package_history"] = {
                    str(key): value
                    for key, value in list(package_history.items())[:MAX_PACKAGE_HISTORY]
                    if isinstance(key, str)
                    and SHA256_RE.fullmatch(key)
                    and isinstance(value, dict)
                }
            # Older builds stored 0x8A150003 as a generic hold. Promote only
            # when the exact WinGet package folder still proves an unreadable
            # file ACL. This in-memory migration is persisted by the next
            # ordinary settings change, avoiding a write merely from startup.
            self.migrated_permission_hold_count = sum(
                upgrade_legacy_winget_permission_hold(record)
                for record in self.data["attempt_holds"].values()
            )
        except (OSError, ValueError, TypeError):
            self.data = self._defaults()
            self.recovered_corrupt_settings = self._quarantine_corrupt_file()

    def _quarantine_corrupt_file(self, *, suffix: str = "bad") -> Path | None:
        """Preserve an unreadable settings file instead of silently discarding it."""
        try:
            stamp = dt.datetime.now().strftime("%Y%m%d-%H%M%S")
            safe_suffix = re.sub(r"[^A-Za-z0-9._-]+", "-", suffix).strip("-") or "bad"
            bad_path = self.path.with_name(f"{self.path.name}.{safe_suffix}-{stamp}")
            os.replace(self.path, bad_path)
            return bad_path
        except OSError:
            return None

    def save(self) -> None:
        atomic_write_text(
            self.path,
            json.dumps(self.data, indent=2, sort_keys=True),
        )


def attempt_hold_classification(record: dict[str, Any]) -> str:
    """Classify a held result from stable WinGet codes, then conservative text clues."""
    if str(record.get("outcome", "")) == "verification-state-change":
        return CLASS_MANUAL_REVIEW
    remediation = record.get("remediation")
    if (
        isinstance(remediation, Mapping)
        and remediation.get("kind") == "winget-existing-install-permissions"
    ):
        return CLASS_MANUAL_REPAIR
    if (
        isinstance(remediation, Mapping)
        and remediation.get("kind") == "rustup-damaged-toolchain"
    ):
        return CLASS_MANUAL_REPAIR
    try:
        code = int(str(record.get("returncode_hex", "")), 0)
    except ValueError:
        code = -1
    # Exact WinGet codes outrank a stored classification so records created by
    # older builds inherit corrected semantics without a destructive migration.
    if code in WINGET_MIGRATION_FAILURE_CODES:
        return CLASS_MIGRATION_REQUIRED
    if code == WINGET_INSTALLER_HASH_MISMATCH:
        return CLASS_MANIFEST_LAG
    if code == WINGET_INSTALLED_FILE_HASH_MISMATCH:
        return CLASS_MANUAL_REPAIR
    if code == MSIX_PACKAGED_SERVICE_REQUIRES_ADMIN:
        return CLASS_MANUAL_REVIEW
    if code in WINGET_NOT_APPLICABLE_CODES or code in WINGET_SCOPE_FAILURE_CODES:
        return CLASS_SCOPE_OR_APPLICABILITY
    if code in WINGET_RETRYABLE_FAILURE_CODES:
        return CLASS_RETRYABLE
    if code in {0x8A15001B, 0x8A15001C, 0x8A15003A, 0x8A15010F}:
        return CLASS_POLICY_BLOCKED
    if code == 0x8A150068:
        return CLASS_MANUAL_REPAIR
    if code in WINGET_SECURITY_FAILURE_CODES or code in {0x8A150050, 0x8A150069, 0x8A150115}:
        return CLASS_MANUAL_REVIEW
    if isinstance(remediation, Mapping) and remediation.get("kind") == "file-in-use":
        return CLASS_RETRYABLE
    stored = str(record.get("classification", ""))
    if stored in KNOWN_CLASSIFICATIONS:
        return stored
    hint = str(record.get("status_hint", "")).casefold()
    if "different install technology" in hint or "reinstall" in hint:
        return CLASS_MIGRATION_REQUIRED
    if "existing file" in hint and "hash" in hint:
        return CLASS_MANUAL_REPAIR
    if "hash mismatch" in hint or "installer hash" in hint:
        return CLASS_MANIFEST_LAG
    if "scope" in hint or "does not match" in hint or "not applicable" in hint:
        return CLASS_SCOPE_OR_APPLICABILITY
    if any(word in hint for word in ("retry", "close", "restart", "network", "busy")):
        return CLASS_RETRYABLE
    if "policy" in hint or "blocked" in hint:
        return CLASS_POLICY_BLOCKED
    if "package permissions" in hint or "repair only this package folder" in hint:
        return CLASS_MANUAL_REPAIR
    return CLASS_MANUAL_REVIEW


def attempt_hold_presentation(record: dict[str, Any]) -> tuple[str, str]:
    classification = attempt_hold_classification(record)
    hint = str(record.get("status_hint", "")).strip()
    outcome = str(record.get("outcome", "failed"))
    if outcome == "verification-state-change":
        return (
            "Installed state changed after attempt - held",
            hint
            or (
                "The installed version changed during the attempt, but the same target "
                "remains offered. Review the package details before deliberately retrying."
            ),
        )
    if str(record.get("returncode_hex", "")).casefold() == f"0x{MSIX_PACKAGED_SERVICE_REQUIRES_ADMIN:08x}":
        return (
            "Packaged service needs administrator - held",
            "Windows refused the MSIX package's service registration (0x80073D28). "
            "A user-scoped app can still contain a service that requires administrator "
            "privileges. Review the app's supported updater or installer with administrator "
            "assistance while preserving the owning Windows account. WinDevPilot will not "
            "change the installation scope or move this user package into its machine "
            "batch. If an authorized elevated attempt also fails, review the vendor and "
            "Windows deployment logs rather than repeatedly retrying.",
        )
    if classification == CLASS_MIGRATION_REQUIRED:
        return (
            "Migration required - different installer technology",
            "The installed technology differs from the offered installer. Use a reviewed "
            "migration workflow instead of repeatedly retrying this upgrade.",
        )
    if classification == CLASS_SCOPE_OR_APPLICABILITY:
        return (
            "Scope or installer mismatch - held",
            "No installer applies to this exact installed scope/system. Verify installed "
            "scope and installer technology before retrying.",
        )
    if classification == CLASS_MANIFEST_LAG:
        return (
            "Manifest lag - retry later",
            hint
            or (
                "WinGet rejected the installer because the manifest hash does not match "
                "the current vendor download. This is normally transient; retry later or "
                "use the vendor updater. WinDevPilot will not bypass the hash check."
            ),
        )
    if classification == CLASS_VERIFICATION_CONFLICT:
        return (
            "Verification conflict - held",
            hint
            or (
                "The package manager reported success, but a fresh read-only scan still "
                "offered this same exact update. WinDevPilot will not retry it as an "
                "ordinary update; wait for provider metadata to change or use Test once "
                "only for a deliberate diagnostic attempt."
            ),
        )
    if classification == CLASS_RETRYABLE:
        remediation = record.get("remediation", {})
        if isinstance(remediation, Mapping) and remediation.get("kind") == "file-in-use":
            return (
                "File in use at last attempt - held",
                "Recorded at the last failed attempt; processes may have exited since then.\n"
                + file_blocker_guidance(remediation.get("evidence", {})),
            )
        return (
            "Retry after prerequisite - held",
            hint or "Resolve the reported busy process, restart, or network condition first.",
        )
    if classification == CLASS_POLICY_BLOCKED:
        return (
            "Blocked by policy - held",
            hint or "A Windows or organizational policy must be reviewed before retrying.",
        )
    if classification == CLASS_MANUAL_REPAIR:
        remediation = record.get("remediation")
        if (
            isinstance(remediation, Mapping)
            and remediation.get("kind") == "rustup-damaged-toolchain"
        ):
            component = str(remediation.get("component", "")).strip()
            missing_path = str(remediation.get("missing_path", "")).strip()
            evidence = ""
            if component:
                evidence += f" Rustup could not remove {component}."
            if missing_path:
                evidence += f" Its recorded file was missing: {missing_path}."
            return (
                "Damaged Rust toolchain - reinstall manually",
                "Rustup rolled the update back because its component metadata and files "
                f"disagree.{evidence} Record this toolchain's installed components and "
                "targets, then manually uninstall and reinstall only this exact toolchain "
                "and restore its extras. This is a separate system repair, not an ordinary "
                "WinDevPilot retry, and WinDevPilot will not perform it automatically.",
            )
        if (
            isinstance(remediation, Mapping)
            and remediation.get("kind") == "winget-existing-install-permissions"
        ):
            blocked_path = str(remediation.get("blocked_path", "")).strip()
            target_text = (
                f" WinGet was denied access to {blocked_path}."
                if blocked_path
                else ""
            )
            return (
                "Existing install permissions need repair",
                "WinGet reached the correct update, but an existing file in this package "
                "folder has unreadable permissions."
                f"{target_text} Repair only this exact WinGet package folder, then release "
                "the hold and retry; do not reset permissions broadly. Package Details "
                "provides a Create repair script button and explains every command it writes.",
            )
        return (
            "Manual repair needed - held",
            hint or "Review the installed package registration before retrying.",
        )
    return (
        "Held after not-applicable result"
        if outcome == "not-applicable"
        else "Held after failed attempt",
        hint or "Review the detailed attempt and installer logs before retrying.",
    )


def build_attempt_hold_record(
    item: UpdateItem,
    entry: dict[str, Any],
    prior: dict[str, Any] | None = None,
) -> dict[str, Any]:
    """Preserve first/last/count history for one exact version transition."""
    prior = prior or {}
    observed_at = str(entry.get("finished_at") or utc_now_iso())
    try:
        prior_count = max(0, int(prior.get("count", 1 if prior else 0)))
    except (TypeError, ValueError):
        prior_count = 0
    classification = attempt_hold_classification(entry)
    return {
        "schema": 1,
        "strategy_revision": (
            WINGET_ATTEMPT_STRATEGY_REVISION
            if item.provider in {WingetProvider.key, MICROSOFT_STORE_PROVIDER_KEY}
            else 1
        ),
        "first_seen": str(prior.get("first_seen") or prior.get("attempted_at") or observed_at),
        "last_seen": observed_at,
        "attempted_at": observed_at,
        "count": prior_count + 1,
        "outcome": str(entry.get("outcome", "failed")),
        "returncode_hex": str(entry.get("returncode_hex", "")),
        "classification": classification,
        "suppressed": True,
        "status_hint": str(entry.get("status_hint", "")),
        "remediation": (
            dict(entry["remediation"]) if isinstance(entry.get("remediation"), Mapping) else {}
        ),
        "item": item_diagnostic_fields(item),
    }


def package_history_key_from_fields(
    provider: str,
    package_id: str,
    scope: str = "",
    source: str = "",
) -> str:
    raw = "\0".join(
        (
            provider.casefold().strip(),
            package_id.casefold().strip(),
            scope.casefold().strip(),
            source.casefold().strip(),
        )
    )
    return hashlib.sha256(raw.encode("utf-8")).hexdigest()


def remember_package_history_event(
    history: Mapping[str, Any],
    *,
    provider: str,
    package_id: str,
    name: str,
    action: str,
    observed_at: str,
    version: str = "",
    scope: str = "",
    source: str = "",
) -> dict[str, dict[str, Any]]:
    """Return bounded package history after one user-authorized successful action."""

    updated = {
        str(key): dict(record)
        for key, record in history.items()
        if isinstance(key, str)
        and SHA256_RE.fullmatch(key)
        and isinstance(record, Mapping)
    }
    key = package_history_key_from_fields(provider, package_id, scope, source)
    prior = updated.get(key, {})
    installed_at = str(prior.get("installed_by_windevpilot_at", ""))
    installed_version = str(prior.get("installed_version", ""))
    if action == "install":
        installed_at = installed_at or observed_at
        installed_version = installed_version or version
    updated[key] = {
        "schema": 1,
        "provider": provider,
        "package_id": package_id,
        "scope": scope,
        "source": source,
        "name": name,
        "installed_by_windevpilot_at": installed_at,
        "installed_version": installed_version,
        "last_serviced_by_windevpilot_at": observed_at,
        "last_serviced_version": version,
        "last_action": action,
    }
    if "inventory_absent_at" in prior:
        updated[key]["inventory_absent_at"] = prior["inventory_absent_at"]
    return dict(
        sorted(
            updated.items(),
            key=lambda pair: _package_history_timestamp(
                pair[1].get("last_serviced_by_windevpilot_at", "")
            )
            or dt.datetime.min.replace(tzinfo=dt.UTC),
            reverse=True,
        )[:MAX_PACKAGE_HISTORY]
    )


def _package_history_timestamp(value: Any) -> dt.datetime | None:
    """Accept only timezone-aware timestamps for history ordering."""

    try:
        timestamp = dt.datetime.fromisoformat(value)
        return timestamp if timestamp.tzinfo is not None else None
    except (TypeError, ValueError, OverflowError):
        return None


def package_history_action_is_current(record: Mapping[str, Any], field: str) -> bool:
    """An action before an observed absence remains history, not current evidence."""

    if "inventory_absent_at" not in record:
        return True
    absent = _package_history_timestamp(record["inventory_absent_at"])
    action = _package_history_timestamp(record.get(field))
    return absent is not None and action is not None and action > absent


def remember_package_history_absences(
    history: Mapping[str, Any],
    installed_items: Sequence[UpdateItem],
    fresh_provider_keys: set[str],
    observed_at: str,
) -> dict[str, Any]:
    """Use complete fresh inventory only; retain the action ledger across gaps.

    Any same-provider/package row conservatively counts as presence, even if
    its scope or source changed. Inventory absence alone cannot explain why a
    package disappeared. Repeated absent scans do not rewrite the timestamp.
    """

    updated = dict(history)
    observed = _package_history_timestamp(observed_at)
    if not history or not fresh_provider_keys or observed is None:
        return updated
    present = {
        (item.provider.casefold().strip(), item.package_id.casefold().strip())
        for item in installed_items
    }
    for key, record in history.items():
        if not isinstance(record, Mapping):
            continue
        fields = tuple(record.get(field, "") for field in ("provider", "package_id", "scope", "source"))
        if not all(isinstance(field, str) for field in fields):
            continue
        provider, package_id, scope, source = fields
        if (
            provider not in fresh_provider_keys
            or provider == PORTABLE_PROVIDER_KEY
            or not package_id
            or scope.casefold().strip() in ("", "unknown")
            or key != package_history_key_from_fields(provider, package_id, scope, source)
            or (provider.casefold().strip(), package_id.casefold().strip()) in present
        ):
            continue
        actions = [
            timestamp for field in ("installed_by_windevpilot_at", "last_serviced_by_windevpilot_at")
            if (timestamp := _package_history_timestamp(record.get(field))) is not None
        ]
        if not actions or observed <= max(actions):
            continue
        if "inventory_absent_at" in record:
            absent = _package_history_timestamp(record["inventory_absent_at"])
            if absent is None or absent >= max(actions):
                continue
        updated[key] = {**record, "inventory_absent_at": observed_at}
    return updated


def package_history_for_item(
    settings_data: Mapping[str, Any], item: UpdateItem
) -> dict[str, Any]:
    """Merge exact and provider/package-only history for Package Details."""

    history = settings_data.get("package_history", {})
    if not isinstance(history, Mapping):
        return {}
    exact_key = package_history_key_from_fields(
        item.provider, item.package_id, item.scope, item.source
    )
    generic_key = package_history_key_from_fields(item.provider, item.package_id)
    records = [
        record
        for key in dict.fromkeys((exact_key, generic_key))
        if isinstance((record := history.get(key)), Mapping)
    ]
    if not records:
        return {}
    installed = [
        record
        for record in records
        if str(record.get("installed_by_windevpilot_at", ""))
    ]
    serviced = [
        record
        for record in records
        if str(record.get("last_serviced_by_windevpilot_at", ""))
    ]
    installed_record = max(
        installed,
        key=lambda record: _package_history_timestamp(
            record.get("installed_by_windevpilot_at", "")
        )
        or dt.datetime.min.replace(tzinfo=dt.UTC),
        default={},
    )
    serviced_record = max(
        serviced,
        key=lambda record: _package_history_timestamp(
            record.get("last_serviced_by_windevpilot_at", "")
        )
        or dt.datetime.min.replace(tzinfo=dt.UTC),
        default={},
    )
    return {
        "installed_at": str(installed_record.get("installed_by_windevpilot_at", "")),
        "installed_version": str(installed_record.get("installed_version", "")),
        "serviced_at": str(serviced_record.get("last_serviced_by_windevpilot_at", "")),
        "serviced_version": str(serviced_record.get("last_serviced_version", "")),
        "last_action": str(serviced_record.get("last_action", "")),
        "installed_current": package_history_action_is_current(
            installed_record, "installed_by_windevpilot_at"
        ),
        "serviced_current": package_history_action_is_current(
            serviced_record, "last_serviced_by_windevpilot_at"
        ),
        "installed_exact": str(installed_record.get("scope", "")) == item.scope
        and str(installed_record.get("source", "")) == item.source,
        "serviced_exact": str(serviced_record.get("scope", "")) == item.scope
        and str(serviced_record.get("source", "")) == item.source,
    }


def forget_package_history_for_item(
    settings_data: dict[str, Any], item: UpdateItem
) -> int:
    history = settings_data.get("package_history", {})
    if not isinstance(history, dict):
        return 0
    keys = {
        package_history_key_from_fields(
            item.provider, item.package_id, item.scope, item.source
        ),
        package_history_key_from_fields(item.provider, item.package_id),
    }
    removed = sum(history.pop(key, None) is not None for key in keys)
    return removed


@dataclasses.dataclass(frozen=True)
class InstalledServiceDate:
    date: str
    source: str
    is_estimate: bool = False
    timestamp: str = ""
    timestamp_precision: str = ""
    history_action: str = ""
    window_start: str = ""
    window_end: str = ""
    observation_kind: str = ""

    @property
    def display_text(self) -> str:
        start = _package_history_timestamp(self.window_start)
        end = _package_history_timestamp(self.window_end)
        if self.is_estimate and start is not None and end is not None:
            start_date = start.astimezone().date().isoformat()
            end_date = end.astimezone().date().isoformat()
            return f"≈ {end_date}" if start_date == end_date else f"≈ {start_date}–{end_date}"
        return f"≈ {self.date}" if self.date and self.is_estimate else self.date

    @property
    def detail_text(self) -> str:
        if self.timestamp:
            rendered = local_observation_time(
                self.timestamp, self.timestamp_precision
            )
            return f"≈ {rendered}" if self.is_estimate else rendered
        return self.display_text

    @property
    def report_text(self) -> str:
        if self.history_action or self.observation_kind:
            return f"{self.detail_text} — {self.source}"
        return self.detail_text


def installation_observation_date_evidence(
    item: UpdateItem,
    observations: Mapping[str, Mapping[str, str]] | None,
) -> InstalledServiceDate:
    """Turn one complete-inventory transition into a bounded date estimate."""

    if not isinstance(observations, Mapping) or not installed_version_is_observable(item.current):
        return InstalledServiceDate("", "")
    record = observations.get(update_observation_identity_key(item))
    if not isinstance(record, Mapping) or any(
        str(record.get(field, "")).casefold() != value.casefold()
        for field, value in (
            ("provider", item.provider),
            ("package_id", item.package_id),
            ("scope", item.scope),
        )
    ):
        return InstalledServiceDate("", "")
    if record.get("state") != "present" or not update_versions_equivalent(
        str(record.get("version", "")), item.current
    ):
        return InstalledServiceDate("", "")
    kind = str(record.get("transition_kind", ""))
    if kind not in {"version-changed", "installed-or-reappeared"}:
        return InstalledServiceDate("", "")
    lower_text = str(record.get("lower_bound_at", ""))
    upper_text = str(record.get("first_seen_at", ""))
    lower = _package_history_timestamp(lower_text)
    upper = _package_history_timestamp(upper_text)
    if lower is None or upper is None or lower >= upper:
        return InstalledServiceDate("", "")
    upper_date = upper.astimezone().date().isoformat()
    source = (
        "Installation/registration appeared between complete inventories"
        if kind == "installed-or-reappeared"
        else "Current version changed between complete inventories"
    )
    return InstalledServiceDate(
        upper_date,
        source,
        is_estimate=True,
        window_start=lower_text,
        window_end=upper_text,
        observation_kind=kind,
    )


def installed_service_date_evidence(
    item: UpdateItem,
    settings_data: Mapping[str, Any],
    installation_observations: Mapping[str, Mapping[str, str]] | None = None,
) -> InstalledServiceDate:
    """Select display evidence without changing provider metadata or reading disk."""

    try:
        native_date = dt.date.fromisoformat(item.installed_date).isoformat()
    except (TypeError, ValueError):
        native_date = ""
    native_timestamp, inferred_precision = normalize_wall_clock_timestamp(
        item.installed_timestamp
    )
    if not native_date and native_timestamp:
        with contextlib.suppress(ValueError):
            native_date = (
                dt.datetime.fromisoformat(native_timestamp)
                .astimezone()
                .date()
                .isoformat()
            )
    # Normalize wording at presentation time, including previously cached rows.
    native_source = item.installed_date_source.replace(
        "Windows uninstall registration", "Windows installed-app registration"
    ).replace("Windows uninstall InstallDate", "Windows installed-app registration InstallDate")
    native = InstalledServiceDate(
        native_date,
        native_source,
        item.installed_date_is_estimate,
        timestamp=native_timestamp,
        timestamp_precision=(item.installed_timestamp_precision or inferred_precision),
    )
    observed = installation_observation_date_evidence(item, installation_observations)

    def best_nonaction_evidence() -> InstalledServiceDate:
        if not observed.date:
            return native
        if native.date and native.date >= observed.date:
            return native
        return observed

    history = settings_data.get("package_history", {})
    if not isinstance(history, Mapping):
        return best_nonaction_evidence()
    # Package-only legacy history is useful in Details, but cannot date a
    # specific installation. Require the exact provider/ID/scope/source here.
    record = history.get(package_history_key_from_fields(
        item.provider, item.package_id, item.scope, item.source
    ))
    if not isinstance(record, Mapping):
        return best_nonaction_evidence()
    candidates: list[tuple[dt.datetime, str, str, str]] = []
    for field, action in (
        ("last_serviced_by_windevpilot_at", record.get("last_action")),
        ("installed_by_windevpilot_at", "install"),
    ):
        if action not in ("install", "update") or not package_history_action_is_current(record, field):
            continue
        try:
            normalized, precision = normalize_wall_clock_timestamp(record.get(field, ""))
            timestamp = dt.datetime.fromisoformat(normalized)
            if timestamp.tzinfo is None:
                continue
            candidates.append((timestamp.astimezone(), action, normalized, precision))
        except (TypeError, ValueError, OverflowError, OSError):
            continue
    if not candidates:
        return best_nonaction_evidence()
    timestamp, action, timestamp_text, timestamp_precision = max(
        candidates, key=lambda candidate: candidate[0]
    )
    history_date = timestamp.date().isoformat()
    observed_lower = _package_history_timestamp(observed.window_start)
    if observed_lower is not None and observed_lower > timestamp:
        return best_nonaction_evidence()
    if native.date and not native.is_estimate:
        native_instant = _package_history_timestamp(native.timestamp)
        if (
            native.date > history_date
            or native_instant is not None
            and native_instant > timestamp
        ):
            return native
    return InstalledServiceDate(
        history_date,
        "Installed by WinDevPilot (verified)" if action == "install"
        else "Updated by WinDevPilot (verified)",
        timestamp=timestamp_text,
        timestamp_precision=timestamp_precision,
        history_action=action,
    )


def winget_permission_repair_target(
    item: UpdateItem,
    record: Mapping[str, Any] | None,
) -> Path | None:
    """Return a narrowly bounded user-package folder eligible for scripted ACL repair."""
    if item.provider != WingetProvider.key or not isinstance(record, Mapping):
        return None
    remediation = record.get("remediation")
    if (
        not isinstance(remediation, Mapping)
        or remediation.get("kind") != "winget-existing-install-permissions"
    ):
        return None
    local_app_data = os.environ.get("LOCALAPPDATA")
    if not local_app_data:
        return None
    allowed_root = Path(local_app_data) / "Microsoft" / "WinGet" / "Packages"
    target_text = str(remediation.get("package_root") or item.installed_location).strip()
    if not target_text:
        blocked_text = str(remediation.get("blocked_path", "")).strip()
        target_text = str(Path(blocked_text).parent) if blocked_text else ""
    target = Path(target_text)
    if (
        not target.is_absolute()
        or not _path_is_within(target, allowed_root)
        or os.path.normcase(str(target)) == os.path.normcase(str(allowed_root))
    ):
        return None
    return target


def upgrade_legacy_winget_permission_hold(record: dict[str, Any]) -> bool:
    """Promote an old generic 0x8A150003 hold only when unreadable ACLs are proven."""
    remediation = record.get("remediation")
    if isinstance(remediation, Mapping) and remediation.get("kind"):
        return False
    if str(record.get("returncode_hex", "")).casefold() != "0x8a150003":
        return False
    item = record.get("item")
    if not isinstance(item, Mapping) or str(item.get("provider", "")).casefold() != "winget":
        return False
    local_app_data = os.environ.get("LOCALAPPDATA")
    installed_location = str(item.get("installed_location", "")).strip()
    if not local_app_data or not installed_location:
        return False
    package_root = Path(installed_location)
    allowed_root = Path(local_app_data) / "Microsoft" / "WinGet" / "Packages"
    if (
        not package_root.is_absolute()
        or not _path_is_within(package_root, allowed_root)
        or os.path.normcase(str(package_root)) == os.path.normcase(str(allowed_root))
    ):
        return False
    try:
        candidates = [
            path
            for path in package_root.iterdir()
            if path.is_file() and path.suffix.casefold() in {".exe", ".dll"}
        ][:24]
    except OSError:
        return False
    blocked_path = ""
    for path in candidates:
        try:
            with path.open("rb") as stream:
                stream.read(1)
        except PermissionError:
            acl_result = run_capture(["icacls.exe", str(path)], timeout=10)
            if acl_result.returncode != 0:
                blocked_path = str(path)
                break
        except OSError:
            continue
    if not blocked_path:
        return False
    record["classification"] = CLASS_MANUAL_REPAIR
    record["status_hint"] = (
        "Failed • existing WinGet package permissions block replacement; "
        "repair only this package folder, then retry"
    )
    record["remediation"] = {
        "kind": "winget-existing-install-permissions",
        "blocked_path": blocked_path,
        "package_root": str(package_root),
        "requires_manual_elevation": True,
        "inferred_from_legacy_hold": True,
    }
    return True


def current_windows_user_sid() -> str:
    """Read the current unelevated account SID without trusting localized labels."""
    if os.name != "nt":
        return ""
    result = run_capture(["whoami.exe", "/user", "/fo", "csv", "/nh"], timeout=10)
    if result.returncode != 0:
        return ""
    match = re.search(r"\bS-\d(?:-\d+){2,}\b", clean_output(result.output), re.IGNORECASE)
    return match.group(0) if match else ""


def write_winget_permission_repair_script(
    item: UpdateItem,
    record: Mapping[str, Any],
) -> Path:
    """Create, but never execute, a reviewable exact-folder ACL repair script."""
    target = winget_permission_repair_target(item, record)
    if target is None:
        raise ValueError("this failure does not expose a safely bounded WinGet package folder")
    target_text = str(target)
    if re.search(r'[%!&|<>^"\r\n]', target_text):
        raise ValueError("the WinGet package folder contains unsupported command characters")
    sid = current_windows_user_sid()
    if not re.fullmatch(r"S-\d(?:-\d+){2,}", sid, re.IGNORECASE):
        raise ValueError("the current Windows account SID could not be determined")
    safe_id = re.sub(r"[^A-Za-z0-9._-]+", "-", item.package_id).strip("-") or "package"
    repairs_dir = app_data_dir() / "repairs"
    repairs_dir.mkdir(parents=True, exist_ok=True)
    script_path = repairs_dir / f"Repair-WinGet-{safe_id}.cmd"
    script = "\n".join(
        [
            "@echo off",
            "setlocal EnableExtensions DisableDelayedExpansion",
            f"title WinDevPilot - repair {item.package_id}",
            "rem Generated by WinDevPilot for one proven WinGet package-permission failure.",
            "rem This script changes only TARGET below. It does not run WinGet, update,",
            "rem uninstall, reinstall, delete, or rename the package.",
            "rem It takes ownership, enables inherited ACLs, grants the recorded normal-user",
            "rem SID Full Control, then attempts to restore that user as owner.",
            "",
            "fltmc >nul 2>&1",
            "if errorlevel 1 (",
            "  echo This narrowly scoped repair must be run as administrator.",
            "  echo Right-click this file and choose Run as administrator.",
            "  pause",
            "  exit /b 740",
            ")",
            "",
            f'set "TARGET={target_text}"',
            f'set "OWNER_SID={sid}"',
            'if not exist "%TARGET%\\" (',
            "  echo The recorded WinGet package folder no longer exists:",
            '  echo   "%TARGET%"',
            "  echo Return to WinDevPilot and scan again.",
            "  pause",
            "  exit /b 2",
            ")",
            "",
            "echo Repairing permissions only for this exact WinGet package folder:",
            'echo   "%TARGET%"',
            "echo.",
            'takeown.exe /f "%TARGET%" /r /d y',
            "if errorlevel 1 goto :failed",
            'icacls.exe "%TARGET%" /inheritance:e /grant:r "*%OWNER_SID%:(OI)(CI)F" /t /c',
            "if errorlevel 1 goto :failed",
            'icacls.exe "%TARGET%" /setowner "*%OWNER_SID%" /t /c',
            "if errorlevel 1 echo Warning: ownership could not be restored, but the access grant succeeded.",
            "",
            "echo.",
            "echo Permission repair completed.",
            "echo Close this window, release the package hold in WinDevPilot, and retry.",
            "pause",
            "exit /b 0",
            "",
            ":failed",
            "echo.",
            "echo Permission repair did not complete. No other package folder was changed.",
            "pause",
            "exit /b 1",
            "",
        ]
    )
    script_path.write_text(script, encoding="utf-8", newline="\r\n")
    return script_path


def attempt_record_matches_current_strategy(record: Any) -> bool:
    """Return false for WinGet failures produced by an obsolete command strategy."""

    if not isinstance(record, dict):
        return False
    item = record.get("item")
    if not isinstance(item, dict) or str(item.get("provider", "")).casefold() not in {
        WingetProvider.key,
        MICROSOFT_STORE_PROVIDER_KEY,
    }:
        return True
    try:
        revision = int(record.get("strategy_revision", 1))
    except (TypeError, ValueError):
        revision = 1
    return revision >= WINGET_ATTEMPT_STRATEGY_REVISION


def applicability_history_key_from_fields(
    *,
    provider: str,
    package_id: str,
    current: str,
    scope: str,
    installed_for: str,
    installed_technology: str,
    installed_location: str,
) -> str:
    """Identify one installed instance while deliberately ignoring the offered version."""

    raw = "\0".join(
        (
            provider.casefold(),
            package_id.casefold(),
            current.casefold(),
            scope.casefold(),
            installed_for.casefold(),
            installed_technology.casefold(),
            os.path.normcase(installed_location.strip().strip('"')).casefold(),
        )
    )
    return hashlib.sha256(raw.encode("utf-8", errors="replace")).hexdigest()


def applicability_history_key(item: UpdateItem) -> str:
    return applicability_history_key_from_fields(
        provider=item.provider,
        package_id=item.package_id,
        current=item.current,
        scope=item.scope,
        installed_for=item.installed_for,
        installed_technology=item.installed_technology,
        installed_location=item.installed_location,
    )


def applicability_history_key_from_diagnostic(value: Any) -> str:
    if not isinstance(value, dict):
        return ""
    return applicability_history_key_from_fields(
        provider=str(value.get("provider", "")),
        package_id=str(value.get("package_id", "")),
        current=str(value.get("installed_version", "")),
        scope=str(value.get("scope", "")),
        installed_for=str(value.get("installed_for", "")),
        installed_technology=str(value.get("installed_technology", "")),
        installed_location=str(value.get("installed_location", "")),
    )


def applicability_history_is_recent(record: Any, *, now: dt.datetime | None = None) -> bool:
    if not isinstance(record, dict):
        return False
    raw_timestamp = str(record.get("last_seen", ""))
    try:
        observed = dt.datetime.fromisoformat(raw_timestamp)
        if observed.tzinfo is None:
            observed = observed.replace(tzinfo=dt.timezone.utc)
        current = now or dt.datetime.now(dt.timezone.utc)
        if current.tzinfo is None:
            current = current.replace(tzinfo=dt.timezone.utc)
        return current - observed <= dt.timedelta(days=APPLICABILITY_HISTORY_TTL_DAYS)
    except (TypeError, ValueError):
        return False


def apply_stored_selection_policy(
    found: Sequence[UpdateItem], settings_data: dict[str, Any]
) -> list[UpdateItem]:
    """Apply ignore rules and exact-candidate attempt holds consistently."""
    ignored = {
        value.casefold() for value in settings_data.get("ignored", []) if isinstance(value, str)
    }
    attempt_holds = settings_data.get("attempt_holds", {})
    if not isinstance(attempt_holds, dict):
        attempt_holds = {}
    restart_pending = settings_data.get("restart_pending", {})
    if not isinstance(restart_pending, dict):
        restart_pending = {}
    boot_id = system_boot_id() if restart_pending else None
    applicability_history = settings_data.get("applicability_history", {})
    if not isinstance(applicability_history, dict):
        applicability_history = {}
    visible: list[UpdateItem] = []
    for item in sorted(
        found, key=lambda value: (value.provider, value.name.casefold(), value.current)
    ):
        if item.ignore_key in ignored or item.legacy_ignore_key in ignored:
            continue
        restart_marker = restart_pending.get(item.verification_identity_key)
        if isinstance(restart_marker, Mapping) and not restarted_after_pending_marker(
            restart_marker, boot_id=boot_id
        ):
            item.selected = False
            if item.classification == CLASS_SIMPLE_UPGRADE:
                set_applicability_prediction(
                    item,
                    PREDICTION_UNKNOWN,
                    confidence="high",
                    source="restart-pending-marker",
                    reasons=(
                        "a previous provider-reported update requires a later Windows boot",
                        "the current offer is not treated as retryable before that restart",
                    ),
                    classification=CLASS_RETRYABLE,
                    status="Restart required to finish previous attempt",
                    guidance=(
                        "Restart Windows before retrying this package. The first complete "
                        "scan after that restart will confirm whether the prior update "
                        "finished or the same target still needs review."
                    ),
                )
            visible.append(item)
            continue
        held_attempt = attempt_holds.get(item.candidate_key)
        if not attempt_record_matches_current_strategy(held_attempt):
            held_attempt = None
        if isinstance(held_attempt, dict):
            item.selected = False
            if item.classification == CLASS_SIMPLE_UPGRADE:
                classification = attempt_hold_classification(held_attempt)
                item.classification = classification
                item.status, item.guidance = attempt_hold_presentation(held_attempt)
                prediction = {
                    CLASS_MIGRATION_REQUIRED: PREDICTION_MIGRATION_REQUIRED,
                    CLASS_SCOPE_OR_APPLICABILITY: PREDICTION_NOT_APPLICABLE,
                    CLASS_MANIFEST_LAG: PREDICTION_STALE,
                    CLASS_MANUAL_REPAIR: PREDICTION_MANUAL_REPAIR,
                }.get(classification, PREDICTION_UNKNOWN)
                returncode_hex = str(held_attempt.get("returncode_hex", ""))
                hold_reason = (
                    "a provider-reported success was contradicted by a fresh exact scan"
                    if classification == CLASS_VERIFICATION_CONFLICT
                    else "learned from a previous exact failed attempt"
                )
                set_applicability_prediction(
                    item,
                    prediction,
                    confidence="high",
                    source="attempt-hold",
                    reasons=(
                        hold_reason,
                        str(held_attempt.get("status_hint", "")).strip(),
                    ),
                    predicted_hresult=(
                        returncode_hex
                        if re.fullmatch(r"0x[0-9A-Fa-f]{8}", returncode_hex)
                        else ""
                    ),
                )
        elif item.provider == WingetProvider.key:
            history = applicability_history.get(applicability_history_key(item))
            try:
                history_count = int(history.get("count", 0)) if isinstance(history, dict) else 0
            except (TypeError, ValueError):
                history_count = 0
            if (
                isinstance(history, dict)
                and attempt_record_matches_current_strategy(history)
                and history_count >= APPLICABILITY_HISTORY_THRESHOLD
                and applicability_history_is_recent(history)
                and attempt_hold_classification(history) == CLASS_SCOPE_OR_APPLICABILITY
                and item.classification == CLASS_SIMPLE_UPGRADE
            ):
                returncode_hex = str(history.get("returncode_hex", ""))
                item.selected = False
                set_applicability_prediction(
                    item,
                    PREDICTION_NOT_APPLICABLE,
                    confidence="medium",
                    source="installed-instance-applicability-history",
                    reasons=(
                        f"this unchanged installed instance had {history_count} prior "
                        "not-applicable attempt(s)",
                        "the offered version changed, but installed version, scope, "
                        "technology, and location did not",
                    ),
                    predicted_hresult=(
                        returncode_hex
                        if re.fullmatch(r"0x[0-9A-Fa-f]{8}", returncode_hex)
                        else ""
                    ),
                    classification=CLASS_SCOPE_OR_APPLICABILITY,
                    status="Prior installers not applicable - review",
                    guidance=(
                        "WinDevPilot remembers repeated not-applicable results for this "
                        "unchanged installed instance. Use Test once if you deliberately want "
                        "to retry; a successful/manual update or changed installation identity "
                        "naturally resets this caution."
                    ),
                )
        visible.append(item)
    return visible


def attempt_hold_scan_summary(
    settings_data: dict[str, Any], active_candidate_keys: set[str]
) -> dict[str, Any]:
    """Expose held exact candidates in read-only diagnostics without mutating settings."""
    raw_holds = settings_data.get("attempt_holds", {})
    if not isinstance(raw_holds, dict):
        raw_holds = {}
    active: list[dict[str, Any]] = []
    stale: list[dict[str, Any]] = []
    for key, record in sorted(raw_holds.items()):
        if not isinstance(key, str) or not isinstance(record, dict):
            continue
        item = record.get("item")
        if not isinstance(item, dict):
            item = {}
        strategy_current = attempt_record_matches_current_strategy(record)
        summary = {
            "candidate_key": key,
            "active": key in active_candidate_keys and strategy_current,
            "provider": str(item.get("provider", "")),
            "name": str(item.get("name", "")),
            "package_id": str(item.get("package_id", "")),
            "scope": str(item.get("scope", "")),
            "classification": str(record.get("classification", "")),
            "outcome": str(record.get("outcome", "")),
            "returncode_hex": str(record.get("returncode_hex", "")),
            "count": record.get("count", 1),
            "first_seen": str(record.get("first_seen", "")),
            "last_seen": str(record.get("last_seen", record.get("attempted_at", ""))),
            "suppressed": bool(record.get("suppressed", False)),
            "strategy_current": strategy_current,
        }
        if summary["active"]:
            active.append(summary)
        else:
            stale.append(summary)
    stale_limit = 25
    return {
        "total": len(active) + len(stale),
        "active_count": len(active),
        "stale_count": len(stale),
        "active": active,
        "stale": stale[:stale_limit],
        "stale_omitted": max(0, len(stale) - stale_limit),
    }


def prune_stale_attempt_holds(
    settings_data: dict[str, Any],
    active_candidate_keys: set[str],
    logger: SessionLogger | None = None,
    *,
    keys: set[str] | None = None,
) -> int:
    """Remove stale attempt holds after logging the full removed records."""
    raw_holds = settings_data.get("attempt_holds", {})
    if not isinstance(raw_holds, dict):
        return 0
    doomed = {
        key: record
        for key, record in raw_holds.items()
        if isinstance(key, str)
        and key not in active_candidate_keys
        and (keys is None or key in keys)
    }
    if not doomed:
        return 0
    if logger is not None:
        logger.event(
            "attempt_holds_pruned",
            pruned_count=len(doomed),
            records=doomed,
        )
    settings_data["attempt_holds"] = {
        key: record for key, record in raw_holds.items() if key not in doomed
    }
    return len(doomed)


def release_attempt_holds(
    settings_data: dict[str, Any],
    keys: set[str],
    logger: SessionLogger | None = None,
) -> int:
    """Deliberately remove selected attempt holds, including active exact candidates."""
    raw_holds = settings_data.get("attempt_holds", {})
    if not isinstance(raw_holds, dict) or not keys:
        return 0
    released = {
        key: record for key, record in raw_holds.items() if isinstance(key, str) and key in keys
    }
    if not released:
        return 0
    if logger is not None:
        logger.event(
            "attempt_holds_released",
            released_count=len(released),
            records=released,
        )
    history_keys = {
        key
        for record in released.values()
        if (key := applicability_history_key_from_diagnostic(record.get("item")))
    }
    raw_history = settings_data.get("applicability_history", {})
    if isinstance(raw_history, dict) and history_keys:
        settings_data["applicability_history"] = {
            key: record for key, record in raw_history.items() if key not in history_keys
        }
        if logger is not None:
            logger.event(
                "applicability_history_released",
                released_count=len(raw_history) - len(settings_data["applicability_history"]),
                history_keys=sorted(history_keys),
            )
    settings_data["attempt_holds"] = {
        key: record for key, record in raw_holds.items() if key not in released
    }
    return len(released)


def retryable_failure_candidate_keys(
    results: Sequence[dict[str, Any]],
    items_by_key: Mapping[str, UpdateItem],
) -> set[str]:
    """Return exact candidates whose latest failed result is safe to offer for retry."""

    retryable: set[str] = set()
    for entry in results:
        if entry.get("success") or entry.get("cancelled"):
            continue
        if str(entry.get("outcome", "")) != "failed":
            continue
        if attempt_hold_classification(entry) != CLASS_RETRYABLE:
            continue
        item = items_by_key.get(str(entry.get("key", "")))
        if item is not None:
            retryable.add(item.candidate_key)
    return retryable


def retryable_failure_context(
    settings_data: Mapping[str, Any], candidate_keys: set[str], *, limit: int = 5
) -> str:
    """Summarize stored retry reasons before deliberately releasing exact holds."""

    raw_holds = settings_data.get("attempt_holds", {})
    if not isinstance(raw_holds, Mapping) or not candidate_keys or limit <= 0:
        return ""
    lines: list[str] = []
    for candidate_key in sorted(candidate_keys):
        record = raw_holds.get(candidate_key)
        if not isinstance(record, Mapping):
            continue
        raw_item = record.get("item", {})
        item = raw_item if isinstance(raw_item, Mapping) else {}
        name = str(item.get("name") or item.get("package_id") or candidate_key).strip()
        hint = str(record.get("status_hint", "")).strip()
        if not hint:
            _status, hint = attempt_hold_presentation(dict(record))
        lines.append(f"- {name}: {hint or 'retry prerequisite was not recorded'}")
    if not lines:
        return ""
    shown = lines[:limit]
    if len(lines) > limit:
        shown.append(f"- …and {len(lines) - limit} more")
    return "Previous failure reasons:\n" + "\n".join(shown)


def item_diagnostic_fields(item: UpdateItem) -> dict[str, Any]:
    return {
        "key": item.key,
        "candidate_key": item.candidate_key,
        "verification_identity_key": item.verification_identity_key,
        "provider": item.provider,
        "name": item.name,
        "package_id": item.package_id,
        "installed_version": item.current,
        "available_version": item.available,
        "source": item.source,
        "scope": item.scope,
        "requires_admin": item.requires_admin,
        "selected": item.selected,
        "status": item.status,
        "instance": item.instance,
        "classification": item.classification,
        "guidance": item.guidance,
        "guidance_url": item.guidance_url,
        "installed_for": item.installed_for,
        "installed_technology": item.installed_technology,
        "installed_location": item.installed_location,
        "installed_size_kb": item.installed_size_kb,
        "installed_size_display": human_size_from_kb(item.installed_size_kb),
        "installed_date": item.installed_date,
        "installed_timestamp": item.installed_timestamp,
        "installed_timestamp_precision": item.installed_timestamp_precision,
        "installed_registration_changed_at": item.installed_registration_changed_at,
        "installed_registration_changed_at_precision": (
            item.installed_registration_changed_at_precision
        ),
        "installed_date_source": item.installed_date_source,
        "installed_date_is_estimate": item.installed_date_is_estimate,
        "product_codes": list(item.product_codes),
        "metadata_sources": list(item.metadata_sources),
        "metadata_confidence": item.metadata_confidence,
        "publisher": item.publisher,
        "description": item.description,
        "architecture": item.architecture,
        "available_technology": item.available_technology,
        "available_scope": item.available_scope,
        "available_upgrade_behavior": item.available_upgrade_behavior,
        "applicability_prediction": item.applicability_prediction,
        "prediction_confidence": item.prediction_confidence,
        "prediction_source": item.prediction_source,
        "prediction_reasons": list(item.prediction_reasons),
        "predicted_hresult": item.predicted_hresult,
        "portable_executable": item.portable_executable,
        "portable_scan_root": item.portable_scan_root,
        "portable_detected_by": item.portable_detected_by,
        "portable_on_path": item.portable_on_path,
        "portable_app_key": item.portable_app_key,
        "portable_publisher": item.portable_publisher,
        "portable_original_filename": item.portable_original_filename,
        "portable_homepage": item.portable_homepage,
        "portable_detection_confidence": item.portable_detection_confidence,
        "portable_evidence_score": item.portable_evidence_score,
        "portable_evidence_reasons": list(item.portable_evidence_reasons),
        "portable_format": item.portable_format,
        "portable_removal_kind": item.portable_removal_kind,
        "portable_removal_target": item.portable_removal_target,
        "portable_removal_reason": item.portable_removal_reason,
        "portable_catalog_package_id": item.portable_catalog_package_id,
        "portable_catalog_name": item.portable_catalog_name,
        "portable_catalog_homepage": item.portable_catalog_homepage,
        "portable_catalog_download_url": item.portable_catalog_download_url,
        "portable_catalog_match_basis": item.portable_catalog_match_basis,
        "portable_catalog_checked_at": item.portable_catalog_checked_at,
        "portable_catalog_error": item.portable_catalog_error,
    }


def build_restart_pending_marker(
    item: UpdateItem,
    entry: Mapping[str, Any],
    *,
    attempt_epoch: float | None = None,
    boot_id: int | None = None,
) -> dict[str, Any]:
    """Remember a reboot-qualified result until a later boot can verify it."""

    observed_epoch = time.time() if attempt_epoch is None else float(attempt_epoch)
    observed_boot = system_boot_id() if boot_id is None else boot_id
    return {
        "schema": 2,
        "identity_key": item.verification_identity_key,
        "attempted_candidate_key": item.candidate_key,
        "attempt_epoch": observed_epoch,
        "boot_id": observed_boot if valid_system_boot_id(observed_boot) else None,
        "attempted_at": str(entry.get("finished_at") or utc_now_iso()),
        "returncode_hex": str(entry.get("returncode_hex", "")),
        "provider": item.provider,
        "item": item_diagnostic_fields(item),
    }


def reconcile_restart_pending_markers(
    settings_data: dict[str, Any],
    current_items: Sequence[UpdateItem],
    refreshed_provider_keys: set[str],
    *,
    boot_id: int | None = None,
) -> dict[str, Any]:
    """Resolve persistent reboot markers only from a current provider update slice."""

    raw_markers = settings_data.get("restart_pending", {})
    markers = dict(raw_markers) if isinstance(raw_markers, Mapping) else {}
    raw_holds = settings_data.get("attempt_holds", {})
    holds = dict(raw_holds) if isinstance(raw_holds, Mapping) else {}
    raw_history = settings_data.get("package_history", {})
    package_history = dict(raw_history) if isinstance(raw_history, Mapping) else {}
    current_by_identity = {item.verification_identity_key: item for item in current_items}
    resolved: list[str] = []
    held: list[str] = []
    changed_target: list[str] = []
    retained: list[str] = []
    current_boot = system_boot_id() if markers and boot_id is None else boot_id

    for identity_key, marker in list(markers.items()):
        if not isinstance(marker, Mapping):
            markers.pop(identity_key, None)
            continue
        raw_item = marker.get("item", {})
        item_data = raw_item if isinstance(raw_item, Mapping) else {}
        provider_key = str(marker.get("provider") or item_data.get("provider", ""))
        if (
            provider_key in refreshed_provider_keys
            and not valid_system_boot_id(marker.get("boot_id"))
            and valid_system_boot_id(current_boot)
        ):
            # Legacy/unavailable boot evidence cannot establish a past restart.
            # Copy before migration so persistence change detection still works.
            marker = {**marker, "schema": 2, "boot_id": current_boot}
            markers[identity_key] = marker
        if provider_key not in refreshed_provider_keys or not restarted_after_pending_marker(
            marker, boot_id=current_boot
        ):
            retained.append(str(identity_key))
            continue

        current = current_by_identity.get(str(identity_key))
        markers.pop(identity_key, None)
        if current is None:
            resolved.append(str(identity_key))
            package_history = remember_package_history_event(
                package_history,
                provider=provider_key,
                package_id=str(item_data.get("package_id", "")),
                name=str(item_data.get("name", "")),
                action="update",
                observed_at=str(marker.get("attempted_at", "")) or utc_now_iso(),
                version=str(item_data.get("available_version", "")),
                scope=str(item_data.get("scope", "")),
                source=str(item_data.get("source", "")),
            )
            continue

        attempted_target = str(item_data.get("available_version", ""))
        target_comparison = compare_strict_numeric_versions(
            current.available, attempted_target
        )
        same_target = (
            current.available.casefold() == attempted_target.casefold()
            or target_comparison == 0
        )
        if not same_target:
            changed_target.append(str(identity_key))
            continue

        prior = holds.get(current.candidate_key)
        conflict_entry = {
            "outcome": "verification-conflict",
            "classification": CLASS_VERIFICATION_CONFLICT,
            "returncode_hex": str(marker.get("returncode_hex", "")),
            "finished_at": utc_now_iso(),
            "status_hint": (
                "Windows restarted after the reported update, but a fresh read-only scan "
                "still offered the same target."
            ),
        }
        holds[current.candidate_key] = build_attempt_hold_record(
            current,
            conflict_entry,
            prior if isinstance(prior, dict) else None,
        )
        held.append(current.candidate_key)

    ordered_holds = sorted(
        holds.items(),
        key=lambda pair: wall_clock_order_key(
            pair[1].get("last_seen", pair[1].get("attempted_at", ""))
        ),
        reverse=True,
    )[:MAX_ATTEMPT_HOLDS]
    settings_data["restart_pending"] = markers
    settings_data["attempt_holds"] = dict(ordered_holds)
    settings_data["package_history"] = package_history
    return {
        "changed": (
            markers != raw_markers
            or dict(ordered_holds) != raw_holds
            or package_history != raw_history
        ),
        "resolved_identity_keys": resolved,
        "history_recorded_identity_keys": resolved,
        "held_candidate_keys": held,
        "changed_target_identity_keys": changed_target,
        "retained_identity_keys": retained,
    }


def command_diagnostic_fields(result: CommandResult) -> dict[str, Any]:
    normalized_code = normalized_exit_code(result.returncode)
    fields: dict[str, Any] = {
        **bounded_diagnostic_output(result.capture_excerpt or result.output),
        "error": redact_sensitive_text(result.exception),
        "command": redact_sensitive_text(subprocess.list2cmdline(result.command)),
        "requested_command": redact_command_parts(result.requested_command),
        "started_at": result.started_at,
        "finished_at": result.finished_at,
        "duration_seconds": result.duration_seconds,
        "process_id": result.process_id,
        "returncode": result.returncode,
        "normalized_returncode": normalized_code,
        "returncode_hex": exit_code_hex(result.returncode),
        "timed_out": result.timed_out,
        "timeout_seconds": result.timeout_seconds,
        "process_returncode": result.process_returncode,
        "capture_bytes": result.capture_bytes,
        "capture_limit_bytes": result.capture_limit_bytes,
        "capture_complete": result.capture_complete,
        "capture_truncated": result.capture_truncated,
        "output_hash_scope": (
            "redacted capture excerpt"
            if result.capture_truncated or not result.capture_complete
            else "complete redacted output"
        ),
    }
    if result.attempts:
        fields["attempts"] = [dict(attempt) for attempt in result.attempts]
    return fields


def command_attempt_diagnostic(
    strategy: str,
    label: str,
    result: CommandResult,
) -> dict[str, Any]:
    """Describe one bounded command attempt without duplicating its full output."""

    return {
        "strategy": strategy,
        "label": label,
        "command": redact_sensitive_text(subprocess.list2cmdline(result.command)),
        "requested_command": redact_command_parts(result.requested_command),
        "started_at": result.started_at,
        "finished_at": result.finished_at,
        "duration_seconds": result.duration_seconds,
        "process_id": result.process_id,
        "returncode": result.returncode,
        "normalized_returncode": normalized_exit_code(result.returncode),
        "returncode_hex": exit_code_hex(result.returncode),
        "timed_out": result.timed_out,
        "timeout_seconds": result.timeout_seconds,
        "process_returncode": result.process_returncode,
        "capture_truncated": result.capture_truncated,
        "capture_complete": result.capture_complete,
        "error": redact_sensitive_text(result.exception),
    }


def command_result_entry(
    item: UpdateItem,
    provider: Provider,
    result: CommandResult,
    *,
    execution_context: str,
    operation: str = "update",
) -> dict[str, Any]:
    warnings = provider.result_warnings(result)
    outcome = provider.outcome(result)
    related_installer_logs = (
        collect_winget_installer_logs(result)
        if provider.key in {WingetProvider.key, MICROSOFT_STORE_PROVIDER_KEY}
        else []
    )
    pip_side_effects = (
        (
            parse_pip_install_output(result.output).to_dict()
            if provider.key == PipProvider.key
            else {}
        )
        if operation == "update"
        else {}
    )
    status_hint = provider.status_hint(result)
    file_blockers: dict[str, Any] = {}
    if not provider.succeeded(result):
        status_hint = winget_installer_failure_hint(result, related_installer_logs, item) or status_hint
        if (
            outcome == "failed"
            and normalized_exit_code(result.returncode) not in WINGET_SECURITY_FAILURE_CODES
            | WINGET_NOT_APPLICABLE_CODES | WINGET_SCOPE_FAILURE_CODES
            | {WINGET_INSTALLER_HASH_MISMATCH, WINGET_INSTALLED_FILE_HASH_MISMATCH,
               0x8A15001B, 0x8A15001C, 0x8A15003A, 0x8A15010F}
        ):
            file_blockers = failed_file_blocker_diagnostic(result)
    remediation: dict[str, Any] = {}
    if provider.key == WingetProvider.key:
        blocked_path = winget_existing_install_permission_failure_path(result)
        if blocked_path:
            remediation = {
                "kind": "winget-existing-install-permissions",
                "blocked_path": blocked_path,
                "package_root": item.installed_location,
                "requires_manual_elevation": True,
            }
    elif provider.key == RustupProvider.key:
        damaged_evidence = rustup_damaged_toolchain_evidence(result.output)
        if damaged_evidence:
            component, missing_path = damaged_evidence
            remediation = {
                "kind": "rustup-damaged-toolchain",
                "toolchain": item.package_id,
                "component": component,
                "missing_path": missing_path,
                "automatic_repair": False,
            }
    if (
        file_blockers.get("state") == "file-users-found"
        and remediation.get("kind") in {None, "winget-existing-install-permissions"}
    ):
        labels: list[str] = []
        for user in file_blockers["users"]:
            label = str(user["name"])
            if user.get("parents"):
                label += f" (launched through {user['parents'][-1]['name']})"
            labels.append(label)
        names = ", ".join(dict.fromkeys(labels))
        status_hint = f"Failed • {names[:240]} was using the file; review its app/task before retrying"
        # Positive file-use evidence takes precedence over a permissions guess.
        # It does not establish that the ACL is correct or authorize any repair.
        remediation = {"kind": "file-in-use", "evidence": redact_log_value(file_blockers)}
    if outcome == "updated" and warnings:
        outcome = "updated-with-warnings"
    if operation == "uninstall" and provider.succeeded(result):
        outcome = "uninstalled-with-warnings" if warnings else "uninstalled"
    return {
        "key": item.key,
        "success": provider.succeeded(result),
        "cancelled": outcome == "canceled",
        **command_diagnostic_fields(result),
        "execution_context": execution_context,
        "launcher_identity": process_identity_diagnostics(),
        "needs_reboot": provider.needs_reboot(result),
        "outcome": outcome,
        "warnings": warnings,
        "provider_already_current_codes": sorted(provider.already_current_codes),
        "provider_not_applicable_codes": sorted(provider.not_applicable_codes),
        "provider_reboot_codes": sorted(provider.reboot_codes),
        "provider_success_codes": sorted(provider.success_codes),
        "status_hint": status_hint,
        "remediation": remediation,
        **({"file_blockers": redact_log_value(file_blockers)} if file_blockers else {}),
        "related_installer_logs": related_installer_logs,
        "pip_side_effects": pip_side_effects,
    }


def operation_result_status(entry: Mapping[str, Any]) -> str:
    """Return the one user-facing status used by rows, overlays, and result logs."""

    success = bool(entry.get("success"))
    cancelled = bool(entry.get("cancelled"))
    warnings = [str(value) for value in entry.get("warnings", ()) if value]
    hint = str(entry.get("status_hint", "")).strip()
    return hint or (
        "Updated with warnings"
        if success and warnings
        else "Updated"
        if success
        else "Cancelled"
        if cancelled
        else "Failed"
    )


def provisional_operation_result_status(entry: Mapping[str, Any]) -> str:
    """Describe an installer report without presenting it as verified package state."""

    if not entry.get("success"):
        return operation_result_status(entry)
    if entry.get("needs_reboot"):
        return "Reported installed — restart required; confirmation pending"
    if verified_winget_installed_version(entry):
        return "Installed version verified" + (" — with warnings" if entry.get("warnings") else "")
    if entry.get("outcome") == "already-current":
        return "Reported already current — confirming…"
    if entry.get("warnings"):
        return "Reported updated with warnings — confirming…"
    return "Reported updated — confirming…"


def overlay_active_update_state(
    update_items: Sequence[UpdateItem],
    package_items: Sequence[UpdateItem],
    active_items: Mapping[str, UpdateItem],
    results: Sequence[Mapping[str, Any]],
    *,
    retain_missing_updates: bool,
) -> tuple[list[UpdateItem], list[UpdateItem]]:
    """Merge a point-in-time scan with provisional live-operation presentation."""

    merged_updates = list(update_items)
    merged_packages = list(package_items)
    update_index = {item.key: index for index, item in enumerate(merged_updates)}
    package_index = {item.key: index for index, item in enumerate(merged_packages)}
    results_by_key = {
        str(entry.get("key", "")): entry
        for entry in results
        if str(entry.get("key", ""))
    }

    for key, active in active_items.items():
        result = results_by_key.get(key)
        status = (
            provisional_operation_result_status(result)
            if result is not None and result.get("success")
            else operation_result_status(result)
            if result is not None
            else active.status
        )
        completed = result is not None

        if key in update_index:
            scanned = merged_updates[update_index[key]]
            merged_updates[update_index[key]] = dataclasses.replace(
                scanned,
                selected=False if completed else active.selected,
                status=status,
            )
        elif retain_missing_updates:
            merged_updates.append(
                dataclasses.replace(
                    active,
                    selected=False if completed else active.selected,
                    status=status,
                )
            )

        if key in package_index:
            installed = merged_packages[package_index[key]]
            merged_packages[package_index[key]] = dataclasses.replace(
                installed,
                selected=False,
                status=status,
            )

    return merged_updates, merged_packages


def diagnostic_failure_entry(
    item: UpdateItem,
    error: str,
    *,
    execution_context: str,
    returncode: int = 2,
    cancelled: bool = False,
) -> dict[str, Any]:
    timestamp = utc_now_iso()
    return {
        "key": item.key,
        "success": False,
        "cancelled": cancelled,
        "returncode": returncode,
        "normalized_returncode": normalized_exit_code(returncode),
        "returncode_hex": exit_code_hex(returncode),
        **bounded_diagnostic_output(""),
        "error": redact_sensitive_text(error),
        "command": "",
        "requested_command": [],
        "execution_context": execution_context,
        "launcher_identity": process_identity_diagnostics(),
        "needs_reboot": False,
        "outcome": "cancelled" if cancelled else "failed",
        "started_at": timestamp,
        "finished_at": timestamp,
        "duration_seconds": 0.0,
        "process_id": None,
        "timed_out": False,
        "timeout_seconds": None,
        "provider_success_codes": [],
        "provider_already_current_codes": [],
        "provider_not_applicable_codes": [],
        "provider_reboot_codes": [],
        "warnings": [],
        "status_hint": "",
        "related_installer_logs": [],
    }


def update_result_counts(results: Sequence[dict[str, Any]], total: int) -> dict[str, int]:
    successful = sum(bool(entry.get("success")) for entry in results)
    already_current = sum(entry.get("outcome") == "already-current" for entry in results)
    not_applicable = sum(entry.get("outcome") == "not-applicable" for entry in results)
    warnings = sum(bool(entry.get("warnings")) for entry in results)
    cancelled = sum(bool(entry.get("cancelled")) for entry in results)
    failed = len(results) - successful - cancelled - not_applicable
    return {
        "successful": successful,
        "updated": max(0, successful - already_current),
        "already_current": already_current,
        "not_applicable": not_applicable,
        "with_warnings": warnings,
        "failed": failed,
        "cancelled": cancelled,
        "skipped": max(0, total - len(results)),
        "reboot_required": sum(bool(entry.get("needs_reboot")) for entry in results),
    }


def reconcile_verification_results(
    expected: dict[str, dict[str, Any]],
    current_items: Sequence[UpdateItem] | Mapping[str, UpdateItem],
    failed_provider_keys: set[str],
    installed_items: Sequence[UpdateItem] | None = None,
) -> dict[str, Any]:
    current_by_key = (
        dict(current_items)
        if isinstance(current_items, Mapping)
        else {item.key: item for item in current_items}
    )
    reconciliation: dict[str, Any] = {
        "no_longer_offered": [],
        "still_pending": [],
        "successor_offered": [],
        "target_changed": [],
        "restart_pending": [],
        "contradicted_success": [],
        "installed_state_changed": [],
        "unverified": [],
        "status_by_key": {},
    }
    for key, prior in expected.items():
        item_data = dict(prior["item"])
        result = dict(prior["result"])
        record = {
            "key": key,
            "item": item_data,
            "reported_outcome": result.get("outcome", ""),
            "reported_success": bool(result.get("success")),
            "needs_reboot": bool(result.get("needs_reboot")),
        }
        provider_key = str(item_data.get("provider", ""))
        if provider_key in failed_provider_keys:
            reconciliation["unverified"].append(record)
            reconciliation["status_by_key"][key] = (
                "Restart required; provider verification inconclusive"
                if result.get("needs_reboot")
                else "Verification inconclusive"
            )
            continue
        current = current_by_key.get(key)
        if result.get("needs_reboot") and current is None:
            reconciliation["restart_pending"].append(record)
            reconciliation["status_by_key"][key] = "Restart required before final verification"
            continue
        if current is None:
            reconciliation["no_longer_offered"].append(record)
            continue
        record["current_item"] = item_diagnostic_fields(current)
        attempted_current = str(item_data.get("installed_version", ""))
        attempted_target = str(item_data.get("available_version", ""))
        current_comparison = compare_strict_numeric_versions(
            current.current, attempted_current
        )
        target_comparison = compare_strict_numeric_versions(
            current.available, attempted_target
        )
        same_installed = (
            current.current.casefold() == attempted_current.casefold()
            or current_comparison == 0
        )
        same_target = (
            current.available.casefold() == attempted_target.casefold()
            or target_comparison == 0
        )
        record["installed_state_changed"] = not same_installed
        record["target_comparison"] = target_comparison
        if result.get("needs_reboot"):
            reconciliation["restart_pending"].append(record)
            reconciliation["status_by_key"][key] = (
                "Restart required before final verification"
                if same_target
                else "Restart required before evaluating changed update target"
            )
            continue
        if same_target:
            reconciliation["still_pending"].append(record)
            if result.get("success"):
                reconciliation["status_by_key"][key] = (
                    "Installed version changed, but the same target remains offered"
                    if not same_installed
                    else "Still offered after reported success"
                )
                reconciliation["contradicted_success"].append(record)
            elif not same_installed:
                reconciliation["status_by_key"][key] = (
                    "Installed state changed after attempt - held"
                )
                reconciliation["installed_state_changed"].append(record)
            elif result.get("outcome") == "not-applicable":
                reconciliation["status_by_key"][key] = "Needs different scope or installer"
            else:
                reconciliation["status_by_key"][key] = "Still offered after failed attempt"
            continue
        if target_comparison == 1:
            if result.get("success") and same_installed:
                record["verification_conflict_reason"] = (
                    "The package manager reported success, but the installed version did "
                    "not change before a newer target appeared."
                )
                reconciliation["contradicted_success"].append(record)
                reconciliation["status_by_key"][key] = (
                    "Installed version unchanged after reported success - held"
                )
                continue
            reconciliation["successor_offered"].append(record)
            reconciliation["status_by_key"][key] = (
                "Newer update available after successful attempt"
                if result.get("success")
                else "Newer update available after attempt"
            )
            continue
        reconciliation["target_changed"].append(record)
        reconciliation["status_by_key"][key] = (
            "Available target changed after successful attempt"
            if result.get("success")
            else "Available target changed after attempt"
        )
    if installed_items is not None:
        for group in ("no_longer_offered", "successor_offered"):
            for record in tuple(reconciliation[group]):
                if not record["reported_success"] or record["needs_reboot"]:
                    continue
                prior = record["item"]
                matches = [item for item in installed_items if all(
                    str(getattr(item, field)).casefold() == str(prior.get(field, "")).casefold()
                    for field in ("provider", "package_id", "scope", "source")
                )]
                target = str(prior.get("available_version", ""))
                verified = len(matches) == 1 and matches[0].key == record["key"] and (
                    matches[0].current.casefold() == target.casefold()
                    or compare_strict_numeric_versions(matches[0].current, target) == 0
                ) and valid_version(target)
                record["installed_verified"] = verified
                if not verified:
                    reconciliation[group].remove(record)
                    reconciliation["unverified"].append(record)
                    reconciliation["status_by_key"][record["key"]] = (
                        "Target installed version not confirmed by fresh inventory"
                    )
    return reconciliation


def process_identity_diagnostics() -> dict[str, Any]:
    return {
        "account_fingerprint": current_account_fingerprint(),
        "is_admin": is_admin(),
        # Avoid the credential redactor's intentionally broad `token` key rule;
        # this value is only a harmless Windows elevation-state label.
        "elevation_type": windows_token_elevation_type(),
        "process_id": os.getpid(),
        "python_version": sys.version,
        "python_executable": sys.executable,
        "machine": platform.machine(),
        "os_version": platform.version(),
        "preferred_encoding": locale.getencoding(),
        "windows_build": windows_build(),
    }


def prune_old_files(
    directory: Path,
    pattern: str,
    *,
    keep: int,
    max_total_bytes: int | None = None,
) -> None:
    if keep < 1 or not directory.exists():
        return
    try:
        files = sorted(
            [path for path in directory.glob(pattern) if path.is_file()],
            key=lambda path: path.stat().st_mtime,
            reverse=True,
        )
    except OSError:
        return
    retained_bytes = 0
    for index, path in enumerate(files):
        try:
            size = path.stat().st_size
        except OSError:
            size = 0
        over_count = index >= keep
        over_bytes = (
            max_total_bytes is not None
            and index > 0
            and retained_bytes + size > max_total_bytes
        )
        if over_count or over_bytes:
            with contextlib.suppress(OSError):
                path.unlink(missing_ok=True)
            continue
        retained_bytes += size


def system_report_path_text(value: str) -> str:
    """Normalize one Windows path and quote it exactly when whitespace requires it."""

    text = str(value).strip()
    if len(text) >= 2 and text[0] == text[-1] and text[0] in {'"', "'"}:
        text = text[1:-1]
    if not text:
        return ""
    without_trailing_separator = text.rstrip("\\/")
    if without_trailing_separator and not re.fullmatch(
        r"[A-Za-z]:",
        without_trailing_separator,
    ):
        text = without_trailing_separator
    return f'"{text}"' if any(character.isspace() for character in text) else text


def is_steam_arp_inventory_item(item: UpdateItem) -> bool:
    return bool(
        item.provider == "winget"
        and item.classification == CLASS_INVENTORY_ONLY
        and STEAM_ARP_PACKAGE_ID_RE.fullmatch(item.package_id)
    )


def installed_channel_display_label(item: UpdateItem, scanner_label: str) -> str:
    """Prefer a proven install channel over the adapter that surfaced its ARP row."""

    if is_steam_arp_inventory_item(item):
        return "Steam"
    return scanner_label


def system_report_update_version(
    installed_item: UpdateItem,
    update_items: Sequence[UpdateItem],
) -> str:
    """Return one unambiguous concrete update version for an installed row."""

    def identity(item: UpdateItem) -> tuple[str, str, str, str]:
        return (
            item.provider.casefold(),
            item.package_id.casefold(),
            item.scope.casefold(),
            (item.source or item.provider).casefold(),
        )

    installed_identity = identity(installed_item)
    matches = [
        item
        for item in update_items
        if item.classification != CLASS_INVENTORY_ONLY and identity(item) == installed_identity
    ]
    if len(matches) > 1:
        same_version = [
            item
            for item in matches
            if item.current.casefold() == installed_item.current.casefold()
        ]
        matches = same_version if len(same_version) == 1 else []
    if len(matches) != 1:
        return ""
    available = matches[0].available.strip()
    if available.casefold() in {
        "",
        "?",
        "unknown",
        "installed",
        "checking…",
        "checking...",
        "n/a",
        "(not available)",
    }:
        return ""
    if available.casefold() == installed_item.current.strip().casefold():
        return ""
    return available


def system_report_text(
    rows: Sequence[Sequence[Any]],
    *,
    provisional_count: int = 0,
    generated_at: dt.datetime | None = None,
    system_build: int | None = None,
    system_architecture: str | None = None,
) -> str:
    """Render a bounded, human-readable snapshot of the All packages inventory."""

    if len(rows) > INSTALLED_INVENTORY_CACHE_MAX_ITEMS:
        raise ValueError("system report exceeded its row limit")
    if provisional_count < 0 or provisional_count > len(rows):
        raise ValueError("system report provisional count was invalid")
    normalized_rows: list[tuple[str, ...]] = []
    for row in rows:
        if len(row) != len(SYSTEM_REPORT_COLUMNS):
            raise ValueError("system report row had the wrong column count")
        fields = tuple(str(value) for value in row)
        if any(len(value) > INSTALLED_INVENTORY_CACHE_MAX_FIELD_CHARS for value in fields):
            raise ValueError("system report field exceeded its size limit")
        normalized_rows.append(fields)

    created = generated_at or dt.datetime.now().astimezone()
    system_build = windows_build() if system_build is None else system_build
    system_architecture = (
        platform.machine() if system_architecture is None else system_architecture
    )
    current_count = len(rows) - provisional_count
    freshness = f"{current_count} current"
    if provisional_count:
        freshness += f", {provisional_count} from previous inventory and still checking"
    lines = [
        f"{APP_NAME} system report",
        "=" * (len(APP_NAME) + len(" system report")),
        f"Generated: {datetime_display_timestamp(created)}",
        f"WinDevPilot version: {APP_VERSION}",
        (
            f"System: Windows build {system_build}; architecture: {system_architecture}"
            if system_build and system_architecture
            else f"System: Windows build {system_build}"
            if system_build
            else f"System architecture: {system_architecture}"
            if system_architecture
            else ""
        ),
        f"Installed packages: {len(rows)}",
        f"Inventory freshness: {freshness}",
    ]
    lines = [line for line in lines if line]
    for index, fields in enumerate(normalized_rows, start=1):
        lines.extend(("", f"#{index}"))
        for label, value in zip(SYSTEM_REPORT_COLUMNS, fields, strict=True):
            if label in SYSTEM_REPORT_INLINE_COLUMNS:
                continue
            if label in SYSTEM_REPORT_OPTIONAL_COLUMNS and not value:
                continue
            value_lines = value.replace("\r\n", "\n").replace("\r", "\n").split("\n")
            lines.append(f"{label}: {value_lines[0]}")
            lines.extend(f"  {continuation}" for continuation in value_lines[1:])
        inline_values = dict(
            zip(SYSTEM_REPORT_INLINE_COLUMNS, fields[-len(SYSTEM_REPORT_INLINE_COLUMNS) :])
        )
        inline_parts = [
            f"{label}: {inline_values[label]}"
            for label in SYSTEM_REPORT_INLINE_COLUMNS
            if inline_values[label]
        ]
        if inline_parts:
            lines.append("    ".join(inline_parts))
    return "\n".join(lines) + "\n"


def write_system_report(
    destination: Path,
    rows: Sequence[Sequence[Any]],
    *,
    provisional_count: int = 0,
    generated_at: dt.datetime | None = None,
) -> Path:
    """Atomically write a user-chosen system report destination."""

    atomic_write_text(
        destination,
        system_report_text(
            rows,
            provisional_count=provisional_count,
            generated_at=generated_at,
        ),
        max_bytes=SYSTEM_REPORT_MAX_BYTES,
    )
    return destination


# ==================== Session logs and diagnostic artifacts ====================

class SessionLogger:
    def __init__(self, log_dir: Path | None = None) -> None:
        log_dir = log_dir or (app_data_dir() / "logs")
        log_dir.mkdir(parents=True, exist_ok=True)
        prune_old_files(
            log_dir,
            "session-*.log",
            keep=50,
            max_total_bytes=SESSION_LOG_RETENTION_BYTES,
        )
        prune_old_files(
            log_dir,
            "session-*.jsonl",
            keep=50,
            max_total_bytes=SESSION_LOG_RETENTION_BYTES,
        )
        self.session_id = uuid.uuid4().hex
        timestamp = dt.datetime.now().strftime("%Y%m%d-%H%M%S-%f")
        self.path = log_dir / f"session-{timestamp}.log"
        self.trace_path = log_dir / f"session-{timestamp}.jsonl"
        self.path.touch()
        self.trace_path.touch()
        self._queue: queue.Queue[tuple[str, Any, threading.Event | None]] = queue.Queue()
        # Bound ordinary records at admission, keeping ordered flush/close barriers
        # independent of capacity. Queue insertion never waits for the disk writer.
        self._queue_state_lock = threading.Lock()
        self._queued_records = 0
        self._dropped_records = 0
        self._pending_dropped_records = 0
        self._queue_depth_high_water = 0
        self._closed = False
        self._writer_error = ""
        self._writer_error_reported = False
        self.crash_path = log_dir / f"session-{timestamp}.crash.log"
        self._fault_stream: Any | None = None
        self._writer = threading.Thread(
            target=self._writer_loop,
            name="wdp-session-logger",
            daemon=True,
        )
        self._writer.start()

    def enable_fault_logging(self) -> bool:
        """Capture native/Python fatal faults that windowless launches would hide."""

        if self._fault_stream is not None:
            return True
        try:
            self._fault_stream = self.crash_path.open(
                "a", encoding="utf-8", errors="replace", buffering=1
            )
            faulthandler.enable(file=self._fault_stream, all_threads=True)
        except (OSError, RuntimeError, ValueError):
            if self._fault_stream is not None:
                with contextlib.suppress(OSError):
                    self._fault_stream.close()
            self._fault_stream = None
            return False
        return True

    def _writer_loop(self) -> None:
        try:
            human_stream = self.path.open("a", encoding="utf-8", errors="replace", buffering=1)
            trace_stream = self.trace_path.open(
                "a", encoding="utf-8", errors="replace", buffering=1
            )
        except OSError as exc:
            self._writer_error = f"{type(exc).__name__}: {exc}"
            self._drain_failed_writer()
            return
        with human_stream, trace_stream:
            while True:
                kind, payload, completion = self._dequeue()
                try:
                    if kind == "write":
                        stamp, message, already_redacted = payload
                        safe_message = (
                            str(message) if already_redacted else redact_sensitive_text(message)
                        ).rstrip()
                        for line in safe_message.splitlines() or [""]:
                            human_stream.write(f"[{stamp}] {line}\n")
                    elif kind == "event":
                        safe_record = redact_log_value(payload)
                        trace_stream.write(
                            json.dumps(safe_record, ensure_ascii=False, sort_keys=True) + "\n"
                        )
                    elif kind in {"flush", "close"}:
                        self._report_dropped_records(human_stream, trace_stream)
                        human_stream.flush()
                        trace_stream.flush()
                    if kind not in {"flush", "close"} and self._queue.empty():
                        self._report_dropped_records(human_stream, trace_stream)
                except Exception as exc:
                    self._writer_error = f"{type(exc).__name__}: {exc}"
                finally:
                    if completion is not None:
                        completion.set()
                    self._queue.task_done()
                if kind == "close":
                    return

    def _drain_failed_writer(self) -> None:
        """Release flush/close waiters if the log files cannot be opened."""

        while True:
            kind, _payload, completion = self._dequeue()
            if completion is not None:
                completion.set()
            self._queue.task_done()
            if kind == "close":
                return

    def write(self, message: str, *, already_redacted: bool = False) -> None:
        if self._closed:
            return
        stamp = clock_display_time(dt.datetime.now().astimezone())
        self._enqueue(("write", (stamp, str(message), already_redacted), None))

    def event(self, event_name: str, **fields: Any) -> None:
        if self._closed:
            return
        record = {
            "schema": LOG_SCHEMA_VERSION,
            "timestamp": utc_now_iso(),
            "session_id": self.session_id,
            "event": event_name,
            **fields,
        }
        self._enqueue(("event", record, None))

    def _enqueue(self, entry: tuple[str, Any, threading.Event | None]) -> bool:
        """Admit bounded ordinary records; preserve nonblocking control ordering."""
        kind = entry[0]
        with self._queue_state_lock:
            if self._closed:
                return False
            if kind not in {"flush", "close"}:
                if self._queued_records >= SESSION_LOG_QUEUE_RECORD_LIMIT:
                    self._dropped_records += 1
                    self._pending_dropped_records += 1
                    return False
                self._queued_records += 1
            elif kind == "close":
                # Admission and close share one lock: no producer can append a
                # record after the writer's final barrier, even if it raced close.
                self._closed = True
            self._queue.put_nowait(entry)
            self._queue_depth_high_water = max(self._queue_depth_high_water, self._queue.qsize())
            return True

    def _dequeue(self) -> tuple[str, Any, threading.Event | None]:
        entry = self._queue.get()
        if entry[0] not in {"flush", "close"}:
            with self._queue_state_lock:
                self._queued_records -= 1
        return entry

    def _report_dropped_records(self, human_stream: Any, trace_stream: Any) -> None:
        """Writer-only evidence of overflow, before acknowledging a flush/close."""
        with self._queue_state_lock:
            count = self._pending_dropped_records
            self._pending_dropped_records = 0
        if not count:
            return
        stamp = clock_display_time(dt.datetime.now().astimezone())
        human_stream.write(f"[{stamp}] Session log capacity exceeded; {count} records omitted.\n")
        trace_stream.write(json.dumps({
            "schema": LOG_SCHEMA_VERSION,
            "timestamp": utc_now_iso(),
            "session_id": self.session_id,
            "event": "logger_records_dropped",
            "count": count,
        }, sort_keys=True) + "\n")

    def queue_depth_metrics(self) -> dict[str, int]:
        with self._queue_state_lock:
            return {
                "current": self._queue.qsize(),
                "high_water": self._queue_depth_high_water,
                "dropped_records": self._dropped_records,
            }

    def flush(self, timeout: float = 5.0) -> bool:
        if self._closed:
            return not self._writer_error
        completion = threading.Event()
        if not self._enqueue(("flush", None, completion)):
            return not self._writer_error
        completed = completion.wait(timeout)
        if self._fault_stream is not None:
            with contextlib.suppress(OSError):
                self._fault_stream.flush()
        return completed and not self._writer_error

    def consume_writer_error(self) -> str:
        if not self._writer_error or self._writer_error_reported:
            return ""
        self._writer_error_reported = True
        return self._writer_error

    def close(self, timeout: float = 5.0) -> bool:
        if self._closed:
            return not self._writer_error
        completion = threading.Event()
        if not self._enqueue(("close", None, completion)):
            return not self._writer_error
        completed = completion.wait(timeout)
        if completed:
            self._writer.join(timeout=0.2)
        if self._fault_stream is not None:
            with contextlib.suppress(Exception):
                faulthandler.disable()
            with contextlib.suppress(OSError):
                self._fault_stream.close()
            self._fault_stream = None
        return completed and not self._writer_error


def _zip_write_json(zip_file: zipfile.ZipFile, name: str, value: Any) -> None:
    zip_file.writestr(
        name,
        json.dumps(redact_log_value(value), indent=2, ensure_ascii=False, sort_keys=True) + "\n",
    )


def _zip_write_text_file(
    zip_file: zipfile.ZipFile,
    source: Path,
    archive_name: str,
    *,
    max_chars: int | None = None,
) -> bool:
    if not source.exists() or not source.is_file():
        return False
    try:
        text = source.read_text(encoding="utf-8", errors="replace")
    except OSError:
        return False
    if max_chars is not None and len(text) > max_chars:
        if archive_name.casefold().endswith(".jsonl"):
            # Keep structured traces line-parseable. A single oversized JSON
            # record is safer to omit than to include as two invalid fragments.
            half = max_chars // 2
            head_end = text.rfind("\n", 0, half)
            tail_start = text.find("\n", max(0, len(text) - half))
            head = text[: head_end + 1] if head_end >= 0 else ""
            tail = text[tail_start + 1 :] if tail_start >= 0 else ""
            omitted = len(text) - len(head) - len(tail)
            marker = json.dumps(
                {
                    "schema": LOG_SCHEMA_VERSION,
                    "event": "diagnostic_bundle_trace_truncated",
                    "omitted_characters": omitted,
                },
                sort_keys=True,
            )
            text = head + marker + "\n" + tail
        else:
            omitted = len(text) - max_chars
            text = (
                text[: max_chars // 2]
                + f"\n\n[WinDevPilot bundle omitted {omitted} characters here]\n\n"
                + text[-max_chars // 2 :]
            )
    zip_file.writestr(archive_name, redact_sensitive_text(text))
    return True


def _recent_log_files(log_dir: Path, *, limit: int = 8) -> list[Path]:
    if not log_dir.exists():
        return []
    try:
        files = [
            path
            for path in log_dir.glob("session-*.*")
            if path.is_file() and path.suffix.casefold() in {".log", ".jsonl"}
        ]
    except OSError:
        return []
    return sorted(files, key=lambda path: path.stat().st_mtime, reverse=True)[:limit]


def create_diagnostic_bundle(
    logger: SessionLogger,
    settings_data: dict[str, Any],
    items: Sequence[UpdateItem],
    *,
    destination_dir: Path | None = None,
) -> Path:
    """Create a local, redacted zip bundle suitable for bug reports or LLM review."""
    logger.flush()
    destination_dir = destination_dir or (app_data_dir() / "diagnostic-bundles")
    destination_dir.mkdir(parents=True, exist_ok=True)
    timestamp = dt.datetime.now().strftime("%Y%m%d-%H%M%S")
    bundle_path = destination_dir / f"{APP_NAME}-diagnostics-{timestamp}.zip"
    temporary_path = destination_dir / f".{bundle_path.name}.{uuid.uuid4().hex}.tmp"
    visible_items = [item_diagnostic_fields(item) for item in items]
    settings_snapshot = {
        "schema": settings_data.get("schema"),
        "providers": settings_data.get("providers", {}),
        "auto_elevate": settings_data.get("auto_elevate"),
        "ignored_count": len(settings_data.get("ignored", []) or []),
        "attempt_hold_count": len(settings_data.get("attempt_holds", {}) or {}),
        "restart_pending_count": len(settings_data.get("restart_pending", {}) or {}),
        "applicability_history_count": len(
            settings_data.get("applicability_history", {}) or {}
        ),
        "package_history_count": len(
            settings_data.get("package_history", {}) or {}
        ),
        "window_geometry_dpi": settings_data.get("window_geometry_dpi"),
    }
    summary_lines = [
        f"# {APP_NAME} diagnostic bundle",
        "",
        f"- App version: {APP_VERSION}",
        f"- Created: {wall_clock_display_timestamp(utc_now_iso())}",
        "",
        "This zip contains redacted diagnostic data from one WinDevPilot session. "
        "It does not include the WinDevPilot Python source code.",
        "",
        "Useful files:",
        "",
        "- `logs/current-session.log`: human-readable operation log",
        "- `trace/current-session.jsonl`: structured diagnostic event trace",
        "- `crash/current-session-crash.log`: fatal Python/native fault trace, when available",
        "- `visible-items.json`: package/update evidence visible in the app",
        "- `settings-summary.json`: non-secret settings summary",
        "- `environment.json`: redacted process/account/environment summary",
        "- `recent-logs-manifest.json`: hashes and metadata for bundled recent logs",
        "",
        "Share this bundle with a maintainer or LLM when diagnosing update failures. "
        "The data is redacted, but review it before sending outside your machine.",
        "",
    ]
    try:
        with zipfile.ZipFile(temporary_path, "w", compression=zipfile.ZIP_DEFLATED) as zip_file:
            zip_file.writestr("README-diagnostic-bundle.md", "\n".join(summary_lines))
            _zip_write_json(zip_file, "environment.json", process_identity_diagnostics())
            _zip_write_json(zip_file, "settings-summary.json", settings_snapshot)
            _zip_write_json(zip_file, "visible-items.json", visible_items)
            _zip_write_text_file(
                zip_file,
                logger.path,
                "logs/current-session.log",
                max_chars=DIAGNOSTIC_CURRENT_LOG_MAX_CHARS,
            )
            _zip_write_text_file(
                zip_file,
                logger.trace_path,
                "trace/current-session.jsonl",
                max_chars=DIAGNOSTIC_CURRENT_LOG_MAX_CHARS,
            )
            _zip_write_text_file(
                zip_file,
                logger.crash_path,
                "crash/current-session-crash.log",
                max_chars=DIAGNOSTIC_CURRENT_LOG_MAX_CHARS,
            )
            recent_manifest: list[dict[str, Any]] = []
            for path in _recent_log_files(logger.path.parent):
                recent_manifest.append(
                    {
                        "name": path.name,
                        "size_bytes": path.stat().st_size,
                        "modified_utc": epoch_storage_timestamp(path.stat().st_mtime),
                        "sha256": _sha256_file(path),
                    }
                )
                archive_name = (
                    "recent-logs/"
                    + ("structured/" if path.suffix == ".jsonl" else "human/")
                    + path.name
                )
                _zip_write_text_file(zip_file, path, archive_name, max_chars=160_000)
            _zip_write_json(zip_file, "recent-logs-manifest.json", recent_manifest)
        bundle_size = temporary_path.stat().st_size
        if bundle_size > DIAGNOSTIC_BUNDLE_MAX_BYTES:
            raise RuntimeError(
                "diagnostic bundle exceeded the "
                f"{DIAGNOSTIC_BUNDLE_MAX_BYTES // (1024 * 1024)} MiB safety limit"
            )
        os.replace(temporary_path, bundle_path)
    finally:
        with contextlib.suppress(OSError):
            temporary_path.unlink()
    prune_old_files(destination_dir, f"{APP_NAME}-diagnostics-*.zip", keep=10)
    return bundle_path


def verified_winget_installed_version(
    entry: Mapping[str, Any], item: UpdateItem | None = None
) -> str:
    """Accept only exact-target evidence, retaining the original attempt identity."""
    proof = entry.get("installed_version_check")
    if not entry.get("success") or entry.get("needs_reboot") or not isinstance(proof, dict):
        return ""
    version = proof.get("installed_version")
    target = proof.get("target_version")
    if (proof.get("status") != "verified" or not isinstance(version, str)
            or not isinstance(target, str) or not valid_version(version)
            or not valid_version(target) or not installed_version_is_observable(version)
            or not installed_version_is_observable(target)
            or not update_versions_equivalent(version, target)):
        return ""
    if item is not None and (
        item.provider != "winget" or entry.get("key") != item.key
        or proof.get("package_id") != item.package_id
        or proof.get("scope") != item.scope or proof.get("source") != item.source
        or not any(update_versions_equivalent(item.current, observed)
                   for observed in (str(proof.get("before_version", "")), version))
        or (item.classification != CLASS_INVENTORY_ONLY
            and not update_versions_equivalent(item.available, target))
    ):
        return ""
    return version


class WingetInstalledVersionChecks:
    """Short sequential reads between installers; never change update outcomes."""

    def __init__(self) -> None:
        self.remaining_seconds = 8.0

    def check(self, item: UpdateItem, entry: dict[str, Any]) -> None:
        if (item.provider != "winget" or item.source != "winget"
                or item.scope not in {"user", "machine"}
                or not entry.get("success") or entry.get("needs_reboot")
                or not valid_package_id(item.package_id) or not valid_version(item.available)
                or not installed_version_is_observable(item.available)):
            return
        proof: dict[str, Any] = {
            "status": "deferred", "package_id": item.package_id, "scope": item.scope,
            "source": item.source, "before_version": item.current,
            "target_version": item.available, "installed_version": "",
        }
        entry["installed_version_check"] = proof
        if self.remaining_seconds < 1:
            proof["reason"] = "Early verification time budget exhausted; final scan will verify."
            return
        started = time.monotonic()
        try:
            result = run_capture([
                "winget", "list", "--id", item.package_id, "--exact",
                "--scope", item.scope, "--source", "winget",
                "--accept-source-agreements", "--disable-interactivity",
            ], timeout=min(3, int(self.remaining_seconds)))
            proof["query"] = command_diagnostic_fields(result)
            proof["status"] = "inconclusive"
            if result.timed_out:
                self.remaining_seconds = 0
            if (result.returncode != 0 or result.exception or result.timed_out
                    or not result.capture_complete or result.capture_truncated):
                return
            rows = []
            for headers in (
                ("Name", "Id", "Version", "Available", "Source"),
                ("Name", "Id", "Version", "Source"),
                ("Name", "Id", "Version"),
            ):
                rows = parse_winget_table_consensus(result.output, headers)
                if rows:
                    break
            if len(rows) != 1:
                return
            row = rows[0]
            if (row.get("Id", "").casefold() != item.package_id.casefold()
                    or row.get("Source", "").casefold() not in {"", "winget"}
                    or not valid_version(row.get("Version", ""))):
                return
            proof["installed_version"] = row["Version"]
            proof["status"] = (
                "verified" if update_versions_equivalent(row["Version"], item.available)
                else "target-not-observed"
            )
        except Exception as exc:
            # An optional read must never abandon remaining selected installers.
            proof["status"] = "inconclusive"
            proof["reason"] = redact_sensitive_text(f"{type(exc).__name__}: {exc}")[:500]
        finally:
            elapsed = time.monotonic() - started
            self.remaining_seconds = max(0.0, self.remaining_seconds - elapsed)
            proof["elapsed_seconds"] = round(elapsed, 3)


def execute_items_direct(
    items: Sequence[UpdateItem],
    providers: dict[str, Provider],
    *,
    execution_context: str = "elevated-helper",
    operation: str = "update",
    precomputed_results: Mapping[str, dict[str, Any]] | None = None,
    on_item_start: Callable[[UpdateItem, int, int], None] | None = None,
    on_item_result: Callable[[UpdateItem, dict[str, Any], int, int], None] | None = None,
) -> list[dict[str, Any]]:
    results: list[dict[str, Any]] = []
    total = len(items)
    precomputed_results = precomputed_results or {}
    installed_version_checks = WingetInstalledVersionChecks()
    for sequence, item in enumerate(items, start=1):
        if on_item_start is not None:
            on_item_start(item, sequence, total)
        if item.key in precomputed_results:
            entry = dict(precomputed_results[item.key])
            results.append(entry)
            if on_item_result is not None:
                on_item_result(item, entry, sequence, total)
            continue
        provider = providers.get(item.provider)
        if provider is None:
            entry = diagnostic_failure_entry(
                item,
                f"unknown provider: {item.provider}",
                execution_context=execution_context,
            )
        else:
            result = (
                provider.uninstall(item) if operation == "uninstall" else provider.update(item)
            )
            entry = command_result_entry(
                item,
                provider,
                result,
                execution_context=execution_context,
                operation=operation,
            )
            if operation == "update":
                installed_version_checks.check(item, entry)
        results.append(entry)
        if on_item_result is not None:
            on_item_result(item, entry, sequence, total)
    return results


def parse_verified_elevation_plan_bytes(raw: bytes, expected_sha256: str) -> dict[str, Any]:
    if not SHA256_RE.fullmatch(expected_sha256):
        raise ValueError("missing or malformed elevation plan hash")
    if len(raw) > MAX_ELEVATION_PLAN_BYTES:
        raise ValueError("elevation plan is unexpectedly large")
    actual_sha256 = hashlib.sha256(raw).hexdigest()
    if not hmac.compare_digest(actual_sha256, expected_sha256):
        raise ValueError("elevation plan changed after administrator launch")
    return loads_strict_json_object(raw, "elevation plan")


def validate_elevation_channel(pipe_name: str, expected_server_process_id: int) -> None:
    if not ELEVATION_PIPE_RE.fullmatch(pipe_name):
        raise ValueError("invalid elevation receipt pipe")
    if (
        isinstance(expected_server_process_id, bool)
        or not isinstance(expected_server_process_id, int)
        or not 1 <= expected_server_process_id <= 0xFFFFFFFF
    ):
        raise ValueError("invalid elevation pipe server process identity")


def reject_json_constant(value: str) -> None:
    raise ValueError(f"unsupported JSON constant in strict JSON payload: {value}")


def reject_duplicate_json_pairs(pairs: Sequence[tuple[str, Any]]) -> dict[str, Any]:
    output: dict[str, Any] = {}
    for key, value in pairs:
        if key in output:
            raise ValueError(f"duplicate JSON key in strict JSON payload: {key}")
        output[key] = value
    return output


def loads_strict_json_object(raw: bytes, label: str) -> dict[str, Any]:
    payload = json.loads(
        raw.decode("utf-8"),
        object_pairs_hook=reject_duplicate_json_pairs,
        parse_constant=reject_json_constant,
    )
    if not isinstance(payload, dict):
        raise ValueError(f"{label} root must be an object")
    return payload


def encoded_elevation_receipt(payload: dict[str, Any]) -> bytes:
    raw = json.dumps(payload, ensure_ascii=False, sort_keys=True, allow_nan=False).encode("utf-8")
    if len(raw) > MAX_ELEVATION_RECEIPT_BYTES:
        raise ValueError("elevated helper receipt is unexpectedly large")
    return raw


def open_elevation_receipt_client(
    pipe_name: str, expected_server_process_id: int
) -> Any:
    """Connect the helper only to the exact caller-owned local pipe."""
    validate_elevation_channel(pipe_name, expected_server_process_id)
    connection = Client(pipe_name, family="AF_PIPE")
    try:
        actual_process_id = named_pipe_server_process_id(connection)
        require_named_pipe_peer_process_id(
            actual_process_id, expected_server_process_id, "server"
        )
        return connection
    except Exception:
        connection.close()
        raise


def send_elevation_receipt(connection: Any, payload: dict[str, Any]) -> None:
    """Send JSON bytes only; never unpickle data across the privilege boundary."""
    connection.send_bytes(encoded_elevation_receipt(payload))


# ==================== Privileged plan validation and UAC transport ====================

def validate_elevation_results(
    results: Any, expected_items: Sequence[UpdateItem]
) -> list[dict[str, Any]]:
    if not isinstance(results, list) or len(results) != len(expected_items):
        raise RuntimeError("elevated helper returned the wrong result count")
    expected_keys = {item.key for item in expected_items}
    expected_by_key = {item.key: item for item in expected_items}
    seen_keys: set[str] = set()
    validated: list[dict[str, Any]] = []
    for entry in results:
        if not isinstance(entry, dict):
            raise RuntimeError("elevated helper returned a malformed result")
        key = str(entry.get("key", ""))
        if key not in expected_keys or key in seen_keys:
            raise RuntimeError("elevated helper returned an unknown or duplicate result")
        if not isinstance(entry.get("success"), bool) or not isinstance(
            entry.get("cancelled"), bool
        ):
            raise RuntimeError("elevated helper returned invalid result state")
        if len(str(entry.get("output", ""))) > MAX_DIAGNOSTIC_OUTPUT_CHARS + 512:
            raise RuntimeError("elevated helper returned oversized process output")
        if "installed_version_check" in entry:
            proof = entry["installed_version_check"]
            expected = expected_by_key[key]
            if (not isinstance(proof, dict) or expected.provider != "winget"
                    or proof.get("package_id") != expected.package_id
                    or proof.get("scope") != expected.scope
                    or proof.get("source") != expected.source
                    or proof.get("before_version") != expected.current
                    or proof.get("target_version") != expected.available
                    or proof.get("status") not in {
                        "verified", "inconclusive", "target-not-observed", "deferred"}
                    or len(json.dumps(proof)) > MAX_DIAGNOSTIC_OUTPUT_CHARS * 6 + 8192
                    or (proof.get("status") == "verified"
                        and not verified_winget_installed_version(entry, expected))):
                raise RuntimeError("elevated helper returned invalid installed-version evidence")
        related_logs = entry.get("related_installer_logs", [])
        if not isinstance(related_logs, list) or len(related_logs) > MAX_RELATED_INSTALLER_LOGS:
            raise RuntimeError("elevated helper returned invalid related installer logs")
        for related_log in related_logs:
            if not isinstance(related_log, dict):
                raise RuntimeError("elevated helper returned a malformed installer log")
            if len(str(related_log.get("output", ""))) > MAX_DIAGNOSTIC_OUTPUT_CHARS + 512:
                raise RuntimeError("elevated helper returned an oversized installer log")
        seen_keys.add(key)
        validated.append(entry)
    if seen_keys != expected_keys:
        raise RuntimeError("elevated helper omitted one or more results")
    return validated


def validate_elevation_transport_test_payload(payload: dict[str, Any]) -> None:
    """Accept only the exact no-op plan used to exercise the UAC transport."""

    expected = {
        "schema": 1,
        "operation": ELEVATION_TRANSPORT_TEST_OPERATION,
        "items": [],
    }
    if payload != expected:
        raise ValueError("invalid elevation transport-test plan")


def validate_elevation_payload(
    payload: dict[str, Any], providers: dict[str, Provider]
) -> list[UpdateItem]:
    if payload.get("schema") != 1 or not isinstance(payload.get("items"), list):
        raise ValueError("unsupported elevation plan")
    operation = str(payload.get("operation", "update"))
    if operation not in {"update", "uninstall"}:
        raise ValueError("unsupported elevated operation")
    expected_fields = {"schema", "items"} | ({"operation"} if "operation" in payload else set())
    if set(payload) != expected_fields:
        raise ValueError("elevation plan root fields do not match the schema")
    if not payload["items"]:
        raise ValueError("elevation plan must contain at least one item")
    if len(payload["items"]) > MAX_ELEVATION_BATCH_ITEMS:
        raise ValueError("elevation plan contains too many items")
    items: list[UpdateItem] = []
    seen_keys: set[str] = set()
    for raw_item in payload["items"]:
        if not isinstance(raw_item, dict):
            raise ValueError("invalid plan item")
        item = UpdateItem.from_plan_dict(raw_item)
        provider = providers.get(item.provider)
        if provider is None or not provider.elevation_allowed:
            raise ValueError(f"provider cannot run elevated: {item.provider}")
        if item.provider == "winget" and item.source.casefold() == "msstore":
            raise ValueError(f"Microsoft Store items must not run elevated: {item.package_id}")
        if not item.requires_admin or item.scope != "machine":
            raise ValueError(f"only machine-scope items may run elevated: {item.package_id}")
        if operation == "uninstall":
            provider.build_uninstall_command(item)
        if item.key in seen_keys:
            raise ValueError(f"duplicate item in elevation plan: {item.package_id}")
        seen_keys.add(item.key)
        items.append(item)
    return items


def partition_elevated_candidates(
    items: Sequence[UpdateItem], providers: dict[str, Provider],
) -> tuple[list[UpdateItem], list[tuple[UpdateItem, dict[str, Any]]]]:
    """Check each local candidate before forming the strictly validated IPC plan."""
    accepted: list[UpdateItem] = []
    rejected: list[tuple[UpdateItem, dict[str, Any]]] = []
    key_counts = Counter(item.key for item in items)
    for item in items:
        try:
            if key_counts[item.key] != 1:
                raise ValueError("duplicate installation identity in selected batch")
            if len(accepted) >= MAX_ELEVATION_BATCH_ITEMS:
                raise ValueError("administrator batch item limit reached")
            validate_elevation_payload(
                {"schema": 1, "items": [item.to_plan_dict()]}, providers
            )
        except ValueError as exc:
            entry = diagnostic_failure_entry(
                item, f"Not started: administrator plan validation rejected this item: {exc}. "
                "Other valid selected packages can continue; rescan before retrying this item.",
                execution_context="local-plan-validation",
            )
            entry["status_hint"] = "Not started — invalid administrator plan item"
            rejected.append((item, entry))
        else:
            accepted.append(item)
    return accepted, rejected


def winget_exact_list_rows(output: str) -> list[dict[str, str]]:
    """Parse exact `winget list` output across table shapes used by WinGet."""
    for headers in (
        ("Name", "Id", "Version", "Available", "Source"),
        ("Name", "Id", "Version", "Source"),
        ("Name", "Id", "Version"),
    ):
        rows = parse_fixed_table(output, headers)
        if rows:
            return rows
    return []


def revalidate_elevated_winget_machine_target(item: UpdateItem) -> dict[str, Any] | None:
    """Verify a machine WinGet target still matches the reviewed plan before elevation work."""
    if item.provider != WingetProvider.key:
        return None
    if item.scope != "machine":
        return diagnostic_failure_entry(
            item,
            "elevated WinGet revalidation refused a non-machine target",
            execution_context="elevated-helper",
        )
    result = run_capture(
        [
            "winget",
            "list",
            "--id",
            item.package_id,
            "--exact",
            "--scope",
            "machine",
            "--accept-source-agreements",
            "--disable-interactivity",
        ],
        timeout=180,
    )
    if normalized_exit_code(result.returncode) == WINGET_NO_APPLICATIONS_FOUND:
        return diagnostic_failure_entry(
            item,
            "target changed after scan: machine WinGet registration is no longer present; rescan required",
            execution_context="elevated-helper",
        )
    if result.returncode not in {0, 1}:
        detail = result.exception or result.output.strip() or "no diagnostic output"
        return diagnostic_failure_entry(
            item,
            f"target revalidation failed before elevated execution: {detail[-500:]}",
            execution_context="elevated-helper",
            returncode=result.returncode or 2,
        )
    parsed_rows = winget_exact_list_rows(result.output)
    if not parsed_rows:
        return diagnostic_failure_entry(
            item,
            "target revalidation inconclusive: WinGet output did not contain a recognizable "
            "installed-package list; rescan required",
            execution_context="elevated-helper",
        )
    rows = [
        row
        for row in parsed_rows
        if row.get("Id", "").casefold() == item.package_id.casefold()
    ]
    if not rows:
        return diagnostic_failure_entry(
            item,
            "target revalidation inconclusive: the returned WinGet list did not confirm "
            "the selected machine package ID; rescan required",
            execution_context="elevated-helper",
        )
    matching_version = [
        row for row in rows if row.get("Version", "").casefold() == item.current.casefold()
    ]
    if not matching_version:
        observed = sorted({row.get("Version", "") for row in rows if row.get("Version", "")})
        return diagnostic_failure_entry(
            item,
            "target changed after scan: machine WinGet registration version is "
            f"{', '.join(observed) or 'unknown'} instead of {item.current}; rescan required",
            execution_context="elevated-helper",
        )
    return None


def revalidate_elevated_targets(items: Sequence[UpdateItem]) -> dict[str, dict[str, Any]]:
    """Return synthetic result entries for elevated items that must not execute."""
    failures: dict[str, dict[str, Any]] = {}
    for item in items:
        failure = revalidate_elevated_winget_machine_target(item)
        if failure is not None:
            failures[item.key] = failure
    return failures


def elevated_helper(
    pipe_name: str,
    expected_server_process_id: int,
    expected_sha256: str,
) -> int:
    """Execute a narrowly validated machine-update plan under one UAC token."""
    try:
        receipt_connection = open_elevation_receipt_client(
            pipe_name, expected_server_process_id
        )
    except Exception:
        return 2
    exit_code = 2
    try:
        try:
            if not is_admin():
                raise PermissionError("helper did not receive an administrator token")
            plan_bytes = receipt_connection.recv_bytes(MAX_ELEVATION_PLAN_BYTES)
            payload = parse_verified_elevation_plan_bytes(plan_bytes, expected_sha256)
            operation = str(payload.get("operation", "update"))
            if operation == ELEVATION_TRANSPORT_TEST_OPERATION:
                validate_elevation_transport_test_payload(payload)
                result_payload = {"schema": 1, "results": [], "error": ""}
                exit_code = 0
            else:
                providers = build_providers()
                items = validate_elevation_payload(payload, providers)
                progress_available = True

                def send_progress(message: dict[str, Any]) -> None:
                    nonlocal progress_available
                    if not progress_available:
                        return
                    try:
                        send_elevation_receipt(receipt_connection, message)
                    except (OSError, ValueError):
                        # Closing the GUI cannot safely recall a batch that already
                        # crossed UAC. Losing the optional progress channel must not
                        # abort the remaining validated machine updates.
                        progress_available = False

                revalidation_failures = revalidate_elevated_targets(items)
                results = execute_items_direct(
                    items,
                    providers,
                    operation=operation,
                    precomputed_results=revalidation_failures,
                    on_item_start=lambda item, sequence, total: send_progress(
                        {
                            "schema": 2,
                            "kind": "item_start",
                            "key": item.key,
                            "sequence": sequence,
                            "total": total,
                        }
                    ),
                    on_item_result=lambda _item, entry, sequence, total: send_progress(
                        {
                            "schema": 2,
                            "kind": "item_result",
                            "result": entry,
                            "sequence": sequence,
                            "total": total,
                        }
                    ),
                )
                result_payload = {"schema": 1, "results": results, "error": ""}
                exit_code = 0 if all(entry["success"] for entry in results) else 1
        except Exception as exc:
            result_payload = {
                "schema": 1,
                "results": [],
                "error": f"{type(exc).__name__}: {exc}",
            }
            exit_code = 2
        send_elevation_receipt(receipt_connection, result_payload)
        return exit_code
    except (OSError, ValueError):
        return 2
    finally:
        receipt_connection.close()


if os.name == "nt":
    from ctypes import wintypes

    class SHELLEXECUTEINFOW(ctypes.Structure):
        _fields_ = [
            ("cbSize", wintypes.DWORD),
            ("fMask", wintypes.ULONG),
            ("hwnd", wintypes.HWND),
            ("lpVerb", wintypes.LPCWSTR),
            ("lpFile", wintypes.LPCWSTR),
            ("lpParameters", wintypes.LPCWSTR),
            ("lpDirectory", wintypes.LPCWSTR),
            ("nShow", ctypes.c_int),
            ("hInstApp", wintypes.HINSTANCE),
            ("lpIDList", wintypes.LPVOID),
            ("lpClass", wintypes.LPCWSTR),
            ("hkeyClass", wintypes.HKEY),
            ("dwHotKey", wintypes.DWORD),
            ("hIcon", wintypes.HANDLE),
            ("hProcess", wintypes.HANDLE),
        ]

    _SHELL32 = ctypes.WinDLL("shell32", use_last_error=True)
    _KERNEL32 = ctypes.WinDLL("kernel32", use_last_error=True)
    _SHELL32.IsUserAnAdmin.argtypes = []
    _SHELL32.IsUserAnAdmin.restype = wintypes.BOOL
    _KERNEL32.CloseHandle.argtypes = [wintypes.HANDLE]
    _KERNEL32.CloseHandle.restype = wintypes.BOOL


def acquire_single_instance() -> bool:
    """Allow one interactive instance per Windows account and logon session."""
    global _INSTANCE_MUTEX
    if os.name != "nt":
        return True
    try:
        create_mutex = _KERNEL32.CreateMutexW
        create_mutex.argtypes = [wintypes.LPVOID, wintypes.BOOL, wintypes.LPCWSTR]
        create_mutex.restype = wintypes.HANDLE
        ctypes.set_last_error(0)
        handle = create_mutex(None, False, single_instance_mutex_name())
        if not handle:
            return True
        if ctypes.get_last_error() == ERROR_ALREADY_EXISTS:
            _KERNEL32.CloseHandle(handle)
            return False
        _INSTANCE_MUTEX = handle
        return True
    except (AttributeError, OSError):
        return True


def elevated_python_executable() -> str:
    """Prefer a base GUI-subsystem Python executable for UAC helper launch."""
    if os.name == "nt":
        base_prefix = Path(getattr(sys, "base_prefix", sys.prefix))
        for name in ("pythonw.exe", "python.exe"):
            base = base_prefix / name
            if base.exists():
                return str(base)
    return sys.executable


def paths_refer_to_same_file(left: str | Path, right: str | Path) -> bool:
    try:
        return Path(left).resolve().samefile(Path(right).resolve())
    except OSError:
        return os.path.normcase(str(Path(left).resolve())) == os.path.normcase(
            str(Path(right).resolve())
        )


def merge_windows_path_entries(*path_values: str) -> str:
    """Merge semicolon PATH values without changing existing command precedence."""

    merged: list[str] = []
    seen: set[str] = set()
    for path_value in path_values:
        # Expand before splitting. A malformed saved value such as
        # ``%PATH%;C:\\Tools`` otherwise becomes one giant pseudo-directory
        # containing embedded semicolons when %PATH% expands.
        expanded_value = os.path.expandvars(path_value)
        for raw_entry in expanded_value.split(os.pathsep):
            entry = os.path.expandvars(raw_entry.strip().strip('"'))
            if not entry:
                continue
            key = os.path.normcase(os.path.normpath(entry)).rstrip("\\/")
            if key in seen:
                continue
            seen.add(key)
            merged.append(entry)
    return os.pathsep.join(merged)


@dataclasses.dataclass(frozen=True, slots=True)
class WindowsPathRefreshReport:
    changed: bool = False
    recovered_tools: tuple[str, ...] = ()
    affected_tools: tuple[str, ...] = ()
    appended_directories: tuple[str, ...] = ()
    user_path_self_referential: bool = False


def _windows_registry_path_values() -> tuple[str, str]:
    if os.name != "nt":
        return "", ""
    try:
        import winreg

        values: list[str] = []
        for hive, subkey in (
            (
                winreg.HKEY_LOCAL_MACHINE,
                r"SYSTEM\CurrentControlSet\Control\Session Manager\Environment",
            ),
            (winreg.HKEY_CURRENT_USER, r"Environment"),
        ):
            try:
                with winreg.OpenKey(hive, subkey) as key:
                    value, _kind = winreg.QueryValueEx(key, "Path")
            except OSError:
                value = ""
            values.append(value if isinstance(value, str) else "")
        return values[0], values[1]
    except (ImportError, OSError):
        return "", ""


def _explicit_windows_path_keys(*path_values: str) -> set[str]:
    """Return explicitly saved directories, excluding recursive %PATH% tokens."""

    keys: set[str] = set()
    for path_value in path_values:
        for raw_entry in path_value.split(os.pathsep):
            entry = raw_entry.strip().strip('"')
            if not entry or entry.casefold() == "%path%":
                continue
            for expanded in os.path.expandvars(entry).split(os.pathsep):
                expanded = expanded.strip().strip('"')
                if expanded:
                    keys.add(os.path.normcase(os.path.normpath(expanded)).rstrip("\\/"))
    return keys


def _known_windows_tool_directories() -> tuple[tuple[Path, tuple[str, ...]], ...]:
    local_app_data_text = os.environ.get("LOCALAPPDATA", "").strip()
    user_profile_text = os.environ.get("USERPROFILE", "").strip()
    program_files_text = os.environ.get("ProgramFiles", "").strip()
    candidates: list[tuple[Path, tuple[str, ...]]] = []
    if local_app_data_text:
        local_app_data = Path(local_app_data_text)
        candidates.extend(
            (
                (local_app_data / "Microsoft" / "WindowsApps", ("winget",)),
                (local_app_data / "Microsoft" / "WinGet" / "Links", ("ninja",)),
                (local_app_data / "Programs" / "PowerShell" / "7", ("pwsh",)),
            )
        )
    if user_profile_text:
        candidates.append(
            (Path(user_profile_text) / ".cargo" / "bin", ("rustup", "cargo"))
        )
    if program_files_text:
        candidates.append((Path(program_files_text) / "PowerShell" / "7", ("pwsh",)))
    return tuple(candidates)


def _tool_file_in_directory(directory: Path, executable: str) -> Path | None:
    for suffix in (".exe", ".cmd", ".bat", ""):
        candidate = directory / f"{executable}{suffix}"
        with contextlib.suppress(OSError):
            if candidate.is_file():
                return candidate
    return None


def known_windows_tool_executable_paths() -> dict[str, str]:
    found: dict[str, str] = {}
    if os.name != "nt":
        return found
    for directory, executables in _known_windows_tool_directories():
        for executable in executables:
            if executable in found:
                continue
            if candidate := _tool_file_in_directory(directory, executable):
                found[executable] = str(candidate)
    return found


def windows_path_refresh_advisory(report: WindowsPathRefreshReport) -> str:
    if not report.user_path_self_referential and not report.affected_tools:
        return ""
    display_names = {
        "winget": "WinGet",
        "rustup": "rustup",
        "cargo": "Cargo",
        "ninja": "Ninja",
        "pwsh": "PowerShell 7",
    }
    tools = ", ".join(display_names.get(tool, tool) for tool in report.affected_tools)
    opening = (
        "The saved user PATH contains a %PATH% self-reference"
        if report.user_path_self_referential
        else "The saved user PATH omits installed tool directories"
    )
    tool_fragment = f" affecting {tools}" if tools else ""
    session_action = (
        "WinDevPilot added verified standard locations to this process only"
        if report.appended_directories
        else "WinDevPilot can use the verified locations in this process"
    )
    return (
        f"{opening}{tool_fragment}. {session_action}, so this scan can proceed; other newly launched apps may still "
        "miss those tools. Repair the user PATH through Windows Environment Variables "
        "using explicit durable folders, and do not copy temporary process-only paths."
    )


def merge_windows_path_refresh_reports(
    *reports: WindowsPathRefreshReport,
) -> WindowsPathRefreshReport:
    return WindowsPathRefreshReport(
        changed=any(report.changed for report in reports),
        recovered_tools=tuple(
            dict.fromkeys(tool for report in reports for tool in report.recovered_tools)
        ),
        affected_tools=tuple(
            dict.fromkeys(tool for report in reports for tool in report.affected_tools)
        ),
        appended_directories=tuple(
            dict.fromkeys(
                directory for report in reports for directory in report.appended_directories
            )
        ),
        user_path_self_referential=any(
            report.user_path_self_referential for report in reports
        ),
    )


def refresh_process_path_from_windows_environment() -> WindowsPathRefreshReport:
    """Refresh PATH and recover verified standard tools without editing Windows settings."""

    if os.name != "nt":
        return WindowsPathRefreshReport()
    machine_path, user_path = _windows_registry_path_values()
    current = os.environ.get("PATH", "")
    refreshed = merge_windows_path_entries(current, machine_path, user_path)
    explicit_keys = _explicit_windows_path_keys(machine_path, user_path)
    known_paths = known_windows_tool_executable_paths()
    before = {tool: shutil.which(tool) for tool in known_paths}
    appended_directories: list[str] = []
    affected_tools: list[str] = []
    refreshed_keys = _explicit_windows_path_keys(refreshed)
    for directory, executables in _known_windows_tool_directories():
        installed_tools = [
            executable
            for executable in executables
            if executable in known_paths
            and os.path.normcase(os.path.normpath(known_paths[executable])).startswith(
                os.path.normcase(os.path.normpath(str(directory))).rstrip("\\/") + os.sep
            )
        ]
        if not installed_tools:
            continue
        directory_text = str(directory)
        directory_key = os.path.normcase(os.path.normpath(directory_text)).rstrip("\\/")
        if directory_key not in explicit_keys:
            affected_tools.extend(installed_tools)
        if directory_key not in refreshed_keys:
            appended_directories.append(directory_text)
            refreshed = merge_windows_path_entries(refreshed, directory_text)
            refreshed_keys.add(directory_key)
    if refreshed and refreshed != current:
        os.environ["PATH"] = refreshed
    after = {tool: shutil.which(tool) for tool in known_paths}
    recovered_tools = [tool for tool in known_paths if not before[tool] and after[tool]]
    user_tokens = {
        token.strip().strip('"').casefold()
        for token in user_path.split(os.pathsep)
        if token.strip()
    }
    return WindowsPathRefreshReport(
        changed=bool(refreshed and refreshed != current),
        recovered_tools=tuple(dict.fromkeys(recovered_tools)),
        affected_tools=tuple(dict.fromkeys(affected_tools)),
        appended_directories=tuple(dict.fromkeys(appended_directories)),
        user_path_self_referential="%path%" in user_tokens,
    )


def user_pip_python_prefix() -> list[str]:
    """Return an interpreter prefix for the user/global pip provider, avoiding this app's venv."""
    if shutil.which("py"):
        return ["py", "-3"]
    python = shutil.which("python")
    if not python:
        raise FileNotFoundError("neither py launcher nor python executable was found on PATH")
    if paths_refer_to_same_file(python, sys.executable):
        raise FileNotFoundError(
            "python on PATH is this WinDevPilot runtime; refusing to scan the app environment"
        )
    return [python]


def launch_elevated_and_wait(
    parameters: Sequence[str],
    *,
    poll_callback: Callable[[], None] | None = None,
    process_started_callback: Callable[[int], None] | None = None,
) -> int:
    if os.name != "nt":
        raise OSError("elevation is only supported on Windows")
    shell_execute = _SHELL32.ShellExecuteExW
    shell_execute.argtypes = [ctypes.POINTER(SHELLEXECUTEINFOW)]
    shell_execute.restype = wintypes.BOOL
    info = SHELLEXECUTEINFOW()
    info.cbSize = ctypes.sizeof(info)
    info.fMask = 0x00000040 | 0x00000100  # NOCLOSEPROCESS | NOASYNC
    info.lpVerb = "runas"
    info.lpFile = elevated_python_executable()
    info.lpParameters = subprocess.list2cmdline(list(parameters))
    info.lpDirectory = os.environ.get("SYSTEMROOT", r"C:\Windows")
    info.nShow = 0  # keep the helper console hidden; UAC remains visible
    ctypes.set_last_error(0)
    if not shell_execute(ctypes.byref(info)):
        error_code = ctypes.get_last_error()
        if error_code == ERROR_CANCELLED:
            raise ElevationCancelled("administrator credential prompt was cancelled")
        if not error_code:
            raise OSError("ShellExecuteExW failed without a Win32 error code")
        raise ctypes.WinError(error_code)
    if not info.hProcess:
        raise OSError("elevated process did not return a process handle")
    try:
        get_process_id = _KERNEL32.GetProcessId
        get_process_id.argtypes = [wintypes.HANDLE]
        get_process_id.restype = wintypes.DWORD
        elevated_process_id = int(get_process_id(info.hProcess))
        if not elevated_process_id:
            raise ctypes.WinError(ctypes.get_last_error())
        if process_started_callback is not None:
            process_started_callback(elevated_process_id)
        wait_for_single_object = _KERNEL32.WaitForSingleObject
        wait_for_single_object.argtypes = [wintypes.HANDLE, wintypes.DWORD]
        wait_for_single_object.restype = wintypes.DWORD
        while True:
            wait_result = wait_for_single_object(
                info.hProcess,
                250 if poll_callback is not None else 0xFFFFFFFF,
            )
            if wait_result == WAIT_FAILED:
                raise ctypes.WinError(ctypes.get_last_error())
            if wait_result != WAIT_TIMEOUT:
                break
            poll_callback()
        if poll_callback is not None:
            poll_callback()
        exit_code = wintypes.DWORD()
        get_exit_code = _KERNEL32.GetExitCodeProcess
        get_exit_code.argtypes = [wintypes.HANDLE, ctypes.POINTER(wintypes.DWORD)]
        get_exit_code.restype = wintypes.BOOL
        if not get_exit_code(info.hProcess, ctypes.byref(exit_code)):
            raise ctypes.WinError(ctypes.get_last_error())
        return int(exit_code.value)
    finally:
        _KERNEL32.CloseHandle(info.hProcess)


def named_pipe_client_process_id(connection: Any) -> int:
    """Return the process ID at the client end of an accepted Windows named pipe."""

    if os.name != "nt":
        raise OSError("named-pipe process identity is only supported on Windows")
    get_client_process_id = _KERNEL32.GetNamedPipeClientProcessId
    get_client_process_id.argtypes = [wintypes.HANDLE, ctypes.POINTER(wintypes.ULONG)]
    get_client_process_id.restype = wintypes.BOOL
    process_id = wintypes.ULONG()
    pipe_handle = wintypes.HANDLE(connection.fileno())
    ctypes.set_last_error(0)
    if not get_client_process_id(pipe_handle, ctypes.byref(process_id)):
        raise ctypes.WinError(ctypes.get_last_error())
    if not process_id.value:
        raise RuntimeError("named-pipe client returned an invalid process identity")
    return int(process_id.value)


def named_pipe_server_process_id(connection: Any) -> int:
    """Return the process ID that created a connected Windows named pipe."""

    if os.name != "nt":
        raise OSError("named-pipe process identity is only supported on Windows")
    get_server_process_id = _KERNEL32.GetNamedPipeServerProcessId
    get_server_process_id.argtypes = [wintypes.HANDLE, ctypes.POINTER(wintypes.ULONG)]
    get_server_process_id.restype = wintypes.BOOL
    process_id = wintypes.ULONG()
    pipe_handle = wintypes.HANDLE(connection.fileno())
    ctypes.set_last_error(0)
    if not get_server_process_id(pipe_handle, ctypes.byref(process_id)):
        raise ctypes.WinError(ctypes.get_last_error())
    if not process_id.value:
        raise RuntimeError("named-pipe server returned an invalid process identity")
    return int(process_id.value)


def require_named_pipe_peer_process_id(
    actual_process_id: int, expected_process_id: int, peer: str
) -> None:
    """Reject a connected pipe whose kernel-reported peer is not expected."""
    if actual_process_id != expected_process_id:
        raise RuntimeError(
            f"elevation pipe {peer} is process {actual_process_id}; "
            f"expected {expected_process_id}"
        )


def _serve_elevation_plan_and_receive_receipt(
    listener: Any,
    plan_bytes: bytes,
    sink: queue.Queue[Any],
    expected_client_process_id: int,
) -> None:
    try:
        while True:
            with listener.accept() as connection:
                actual_process_id = named_pipe_client_process_id(connection)
                try:
                    require_named_pipe_peer_process_id(
                        actual_process_id, expected_client_process_id, "client"
                    )
                except RuntimeError:
                    continue
                connection.send_bytes(plan_bytes)
                while True:
                    try:
                        raw = connection.recv_bytes(MAX_ELEVATION_RECEIPT_BYTES)
                    except EOFError:
                        break
                    sink.put((raw, ""))
                return
    except Exception as exc:
        sink.put((None, f"{type(exc).__name__}: {exc}"))


def elevation_helper_arguments(
    pipe_name: str, expected_server_process_id: int, plan_sha256: str
) -> list[str]:
    """Build the non-secret arguments needed by the elevated helper."""
    validate_elevation_channel(pipe_name, expected_server_process_id)
    if not SHA256_RE.fullmatch(plan_sha256):
        raise ValueError("missing or malformed elevation plan hash")
    return [
        str(SCRIPT_PATH),
        "--elevated-pipe",
        pipe_name,
        "--elevated-parent-pid",
        str(expected_server_process_id),
        "--elevated-plan-sha256",
        plan_sha256,
    ]


def execute_elevated_batch(
    items: Sequence[UpdateItem],
    *,
    operation: str = "update",
    progress_callback: Callable[
        [str, UpdateItem, dict[str, Any] | None, int, int, int], None
    ]
    | None = None,
) -> list[dict[str, Any]]:
    if operation not in {"update", "uninstall", ELEVATION_TRANSPORT_TEST_OPERATION}:
        raise ValueError(f"unsupported elevated operation: {operation}")
    if operation == ELEVATION_TRANSPORT_TEST_OPERATION:
        if items:
            raise ValueError("elevation transport test must not contain package items")
    elif not items:
        raise ValueError("elevated package operation must contain at least one item")
    plan = {
        "schema": 1,
        "operation": operation,
        "items": [item.to_plan_dict() for item in items],
    }
    plan_bytes = json.dumps(plan, indent=2).encode("utf-8")
    if len(plan_bytes) > MAX_ELEVATION_PLAN_BYTES:
        raise RuntimeError("elevation plan is unexpectedly large")
    plan_sha256 = hashlib.sha256(plan_bytes).hexdigest()
    pipe_name = rf"\\.\pipe\{APP_NAME}-{uuid.uuid4().hex}"
    parent_process_id = os.getpid()
    validate_elevation_channel(pipe_name, parent_process_id)
    listener = Listener(pipe_name, family="AF_PIPE")
    receipt_queue: queue.Queue[Any] = queue.Queue(maxsize=MAX_ELEVATION_BATCH_ITEMS * 2 + 4)
    receiver: threading.Thread | None = None
    progressive_results: dict[str, dict[str, Any]] = {}
    started_keys: set[str] = set()
    receipt_errors: list[str] = []
    final_payload: dict[str, Any] | None = None
    active_progress: tuple[UpdateItem, int, int, float] | None = None
    next_heartbeat_seconds = 30

    def dispatch_progress(
        kind: str,
        item: UpdateItem,
        entry: dict[str, Any] | None,
        sequence: int,
        total: int,
        elapsed_seconds: int = 0,
    ) -> None:
        if progress_callback is not None:
            progress_callback(kind, item, entry, sequence, total, elapsed_seconds)

    def consume_receipts() -> None:
        nonlocal final_payload, active_progress, next_heartbeat_seconds
        while True:
            try:
                receipt_bytes, receipt_error = receipt_queue.get_nowait()
            except queue.Empty:
                break
            if receipt_error:
                receipt_errors.append(str(receipt_error))
                continue
            if not receipt_bytes:
                receipt_errors.append("elevated helper returned an empty progress message")
                continue
            message = loads_strict_json_object(receipt_bytes, "elevated helper message")
            if message.get("schema") == 1:
                if set(message) != {"schema", "results", "error"} or final_payload is not None:
                    raise RuntimeError("invalid or duplicate elevated helper completion receipt")
                final_payload = message
                continue
            if message.get("schema") != 2:
                raise RuntimeError("invalid elevated helper progress schema")
            kind = str(message.get("kind", ""))
            sequence = int(message.get("sequence", 0))
            total = int(message.get("total", 0))
            if total != len(items) or not 1 <= sequence <= len(items):
                raise RuntimeError("elevated helper progress sequence is invalid")
            expected_item = items[sequence - 1]
            if kind == "item_start":
                if set(message) != {"schema", "kind", "key", "sequence", "total"}:
                    raise RuntimeError("malformed elevated item-start progress")
                key = str(message.get("key", ""))
                if key != expected_item.key or key in started_keys:
                    raise RuntimeError("unexpected or duplicate elevated item-start progress")
                started_keys.add(key)
                active_progress = (expected_item, sequence, total, time.monotonic())
                next_heartbeat_seconds = 30
                dispatch_progress(kind, expected_item, None, sequence, total)
                continue
            if kind == "item_result":
                if set(message) != {"schema", "kind", "result", "sequence", "total"}:
                    raise RuntimeError("malformed elevated item-result progress")
                validated = validate_elevation_results([message.get("result")], [expected_item])[0]
                if expected_item.key in progressive_results:
                    raise RuntimeError("duplicate elevated item-result progress")
                progressive_results[expected_item.key] = validated
                active_progress = None
                dispatch_progress(kind, expected_item, validated, sequence, total)
                continue
            raise RuntimeError(f"unsupported elevated helper progress kind: {kind}")

        if active_progress is not None:
            item, sequence, total, started_at = active_progress
            elapsed = int(time.monotonic() - started_at)
            if elapsed >= next_heartbeat_seconds:
                dispatch_progress("heartbeat", item, None, sequence, total, elapsed)
                next_heartbeat_seconds = 90 if next_heartbeat_seconds == 30 else next_heartbeat_seconds + 60

    def start_receipt_receiver(elevated_process_id: int) -> None:
        nonlocal receiver
        receiver = threading.Thread(
            target=_serve_elevation_plan_and_receive_receipt,
            args=(listener, plan_bytes, receipt_queue, elevated_process_id),
            name="WinDevPilot-elevation-receipt",
            daemon=True,
        )
        receiver.start()

    try:
        exit_code = launch_elevated_and_wait(
            elevation_helper_arguments(pipe_name, parent_process_id, plan_sha256),
            poll_callback=consume_receipts,
            process_started_callback=start_receipt_receiver,
        )
        if receiver is None:
            raise RuntimeError("elevated helper started without a bound receipt receiver")
        receiver.join(timeout=10)
        consume_receipts()
        if receiver.is_alive():
            listener.close()
            receiver.join(timeout=2)
            raise RuntimeError(f"elevated helper exited {exit_code} without completing its receipt")
        if receipt_errors:
            raise RuntimeError(
                f"elevated helper receipt failed after exit {exit_code}: {receipt_errors[-1]}"
            )
        if final_payload is None:
            raise RuntimeError(f"elevated helper exited {exit_code} without a completion receipt")
        payload = final_payload
        if exit_code not in {0, 1}:
            detail = str(payload.get("error") or "receipt cannot be trusted")
            raise RuntimeError(f"elevated helper exited {exit_code}: {detail}")
        if payload.get("error"):
            raise RuntimeError(str(payload["error"]))
        validated_results = validate_elevation_results(payload.get("results"), items)
        if progressive_results:
            final_by_key = {str(entry.get("key", "")): entry for entry in validated_results}
            for key, progress_entry in progressive_results.items():
                if final_by_key.get(key) != progress_entry:
                    raise RuntimeError("elevated helper completion contradicted streamed progress")
        return validated_results
    finally:
        listener.close()
        if receiver is not None and receiver.is_alive():
            receiver.join(timeout=2)


def secondary_toolbar_action_states(
    *,
    busy: bool,
    scan_active: bool,
    all_packages: bool,
    retry_available: bool,
    report_available: bool,
    cache_clear_inflight: bool = False,
) -> dict[str, str]:
    """Return menu states for actions consolidated behind the toolbar sprocket."""

    idle_state = "normal" if not busy and not scan_active else "disabled"
    update_view_state = "normal" if idle_state == "normal" and not all_packages else "disabled"
    return {
        "retry_failed": (
            "normal" if update_view_state == "normal" and retry_available else "disabled"
        ),
        "select_recommended": update_view_state,
        "select_all": update_view_state,
        "select_none": update_view_state,
        "test_once": update_view_state,
        "save_system_report": (
            "normal" if idle_state == "normal" and report_available else "disabled"
        ),
        "manage_ignores": idle_state,
        "holds": idle_state,
        "clean_graphics_cache": "disabled" if cache_clear_inflight else idle_state,
        "providers": "normal",
    }


LIGHT_PALETTE: dict[str, str] = {
    "mode": "light",
    "window": "#f3f7fb",
    "surface": "#ffffff",
    "surface_alt": "#f7fbff",
    "text": "#111827",
    "title": "#102033",
    "text_soft": "#52606d",
    "link": "#0645ad",
    "text_secondary": "#374151",
    "accent": "#2563eb",
    "accent_2": "#06b6d4",
    "busy": "#f97316",
    "busy_2": "#ef4444",
    "busy_pulse": "#fff7ed",
    "idle": "#e8f6ee",
    "idle_text": "#166534",
    "busy_soft": "#fff7ed",
    "busy_text": "#9a3412",
    "accent_text": "#f8fbff",
    "selected": "#edf7ff",
    "hover": "#f1f6fb",
    "review": "#fff7df",
    "admin": "#f0ecff",
    "border": "#d7e2ee",
    "entry_surface": "#eefbf9",
    "danger_surface": "#fee2e2",
    "danger_text": "#991b1b",
    "tooltip_surface": "#fffef7",
    "tooltip_text": "#111827",
    "tooltip_border": "#cbd5e1",
    "text_panel": "#f7f9fb",
    "log_success": "#15803d",
    "log_warning": "#c2410c",
    "log_failure": "#b91c1c",
    "log_info": "#2563eb",
    "log_dim": "#64748b",
    "health_path": "#1d4ed8",
    "health_command": "#6d28d9",
    "scan_fresh": "#065f46",
    "scan_stale": "#111827",
    "disabled_text": "#6b7280",
    "button": "#ffffff",
    "button_active": "#eef6ff",
    "button_disabled": "#f3f4f6",
    "update_ready": "#b7ef49",
    "update_ready_active": "#a3e635",
    "update_ready_text": "#102000",
    "update_ready_border": "#18240e",
    "entry_border": "#cbd5e1",
    "scrollbar": "#d8e2ef",
    "scrollbar_active": "#c7d6e8",
    "scrollbar_trough": "#eef3f8",
    "progress": "#16a34a",
    "progress_trough": "#e5edf6",
    "chrome_active_caption": "#dbeafe",
    "chrome_active_text": "#0f172a",
    "chrome_active_border": "#2563eb",
    "chrome_inactive_caption": "#f8fafc",
    "chrome_inactive_text": "#64748b",
    "chrome_inactive_border": "#cbd5e1",
    "header_left": "#e8f3ff",
    "header_mid": "#fbfdff",
    "header_right": "#e5faf5",
    "header_border": "#d8e7f3",
}

DARK_PALETTE: dict[str, str] = {
    "mode": "dark",
    "window": "#0b1220",
    "surface": "#111827",
    "surface_alt": "#162033",
    "text": "#e5edf6",
    "title": "#f8fbff",
    "text_soft": "#a7b4c5",
    "link": "#6ea8fe",
    "text_secondary": "#cbd5e1",
    "accent": "#60a5fa",
    "accent_2": "#2dd4bf",
    "busy": "#f59e0b",
    "busy_2": "#fb7185",
    "busy_pulse": "#fde68a",
    "idle": "#0f2f28",
    "idle_text": "#a7f3d0",
    "busy_soft": "#332314",
    "busy_text": "#fed7aa",
    "accent_text": "#f8fbff",
    "selected": "#172a45",
    "hover": "#182337",
    "review": "#1b2433",
    "admin": "#221f35",
    "border": "#334155",
    "entry_surface": "#102a34",
    "danger_surface": "#3a1419",
    "danger_text": "#fecaca",
    "tooltip_surface": "#172033",
    "tooltip_text": "#f8fbff",
    "tooltip_border": "#475569",
    "text_panel": "#0f172a",
    "log_success": "#86efac",
    "log_warning": "#fbbf24",
    "log_failure": "#f87171",
    "log_info": "#93c5fd",
    "log_dim": "#94a3b8",
    "health_path": "#93c5fd",
    "health_command": "#c4b5fd",
    "scan_fresh": "#86efac",
    "scan_stale": "#f8fafc",
    "disabled_text": "#64748b",
    "button": "#172033",
    "button_active": "#1f2c44",
    "button_disabled": "#111827",
    "update_ready": "#84cc16",
    "update_ready_active": "#a3e635",
    "update_ready_text": "#071300",
    "update_ready_border": "#020617",
    "entry_border": "#475569",
    "scrollbar": "#334155",
    "scrollbar_active": "#475569",
    "scrollbar_trough": "#0b1220",
    "progress": "#4ade80",
    "progress_trough": "#111827",
    "chrome_active_caption": "#0f2a44",
    "chrome_active_text": "#f8fafc",
    "chrome_active_border": "#2dd4bf",
    "chrome_inactive_caption": "#151923",
    "chrome_inactive_text": "#94a3b8",
    "chrome_inactive_border": "#334155",
    "header_left": "#0f1f33",
    "header_mid": "#111827",
    "header_right": "#0f2f2a",
    "header_border": "#26384d",
}

MENU_THEME_ROLES: dict[str, str] = {
    "background": "surface",
    "foreground": "text",
    "activebackground": "button_active",
    "activeforeground": "text",
    "disabledforeground": "disabled_text",
    "selectcolor": "accent",
}


def windows_app_theme_mode() -> str | None:
    """Read Windows' app theme, preserving the current UI on transient registry errors."""

    if os.name != "nt":
        return "light"
    try:
        import winreg

        with winreg.OpenKey(
            winreg.HKEY_CURRENT_USER,
            r"Software\Microsoft\Windows\CurrentVersion\Themes\Personalize",
        ) as key:
            value, _kind = winreg.QueryValueEx(key, "AppsUseLightTheme")
        return "dark" if int(value) == 0 else "light"
    except Exception:
        return None


def system_prefers_dark_app_mode() -> bool:
    """Return True when Windows app theme is dark; safely fall back to light elsewhere."""

    return windows_app_theme_mode() == "dark"


def system_client_animations_enabled() -> bool:
    """Honor Windows' client-area animation accessibility preference."""

    if os.name != "nt":
        return True
    enabled = ctypes.c_int(1)
    try:
        user32 = ctypes.WinDLL("user32", use_last_error=True)
        user32.SystemParametersInfoW.argtypes = [
            ctypes.c_uint,
            ctypes.c_uint,
            ctypes.c_void_p,
            ctypes.c_uint,
        ]
        user32.SystemParametersInfoW.restype = ctypes.c_int
        if user32.SystemParametersInfoW(0x1042, 0, ctypes.byref(enabled), 0):
            return bool(enabled.value)
    except (AttributeError, OSError):
        pass
    return True


def preferred_windows_ui_fonts(root: Any) -> tuple[str, str]:
    """Prefer Win11's variable UI faces while retaining broad Tk compatibility."""

    try:
        import tkinter.font as tkfont

        families = {str(name).casefold(): str(name) for name in tkfont.families(root)}
    except Exception:
        return "Segoe UI", "Segoe UI"
    text = families.get("segoe ui variable text", families.get("segoe ui", "Segoe UI"))
    display = families.get("segoe ui variable display", text)
    return text, display


def preferred_windows_monospace_font(root: Any) -> str:
    """Choose one installed coding face for logs, commands, and aligned data."""

    try:
        import tkinter.font as tkfont

        families = {str(name).casefold(): str(name) for name in tkfont.families(root)}
    except Exception:
        return "Consolas"
    for candidate in ("Cascadia Code", "Cascadia Mono", "JetBrains Mono", "Fira Code", "Consolas"):
        if installed := families.get(candidate.casefold()):
            return installed
    return "TkFixedFont"


def palette_for_mode(mode: str) -> dict[str, str]:
    if mode not in {"light", "dark"}:
        raise ValueError(f"unsupported app palette mode: {mode}")
    return dict(DARK_PALETTE if mode == "dark" else LIGHT_PALETTE)


def app_palette() -> dict[str, str]:
    return palette_for_mode("dark" if system_prefers_dark_app_mode() else "light")


def window_monitor_work_area(window: Any) -> tuple[int, int, int, int]:
    """Return the usable pixel rectangle for the monitor nearest a Tk window."""

    fallback = (0, 0, int(window.winfo_screenwidth()), int(window.winfo_screenheight()))
    if os.name != "nt":
        return fallback

    class Rect(ctypes.Structure):
        _fields_ = [
            ("left", ctypes.c_long),
            ("top", ctypes.c_long),
            ("right", ctypes.c_long),
            ("bottom", ctypes.c_long),
        ]

    class MonitorInfo(ctypes.Structure):
        _fields_ = [
            ("cbSize", ctypes.c_uint),
            ("rcMonitor", Rect),
            ("rcWork", Rect),
            ("dwFlags", ctypes.c_uint),
        ]

    try:
        user32 = ctypes.WinDLL("user32", use_last_error=True)
        user32.MonitorFromWindow.argtypes = [ctypes.c_void_p, ctypes.c_uint]
        user32.MonitorFromWindow.restype = ctypes.c_void_p
        user32.GetMonitorInfoW.argtypes = [ctypes.c_void_p, ctypes.POINTER(MonitorInfo)]
        user32.GetMonitorInfoW.restype = ctypes.c_int
        monitor = user32.MonitorFromWindow(int(window.winfo_id()), 2)
        info = MonitorInfo(cbSize=ctypes.sizeof(MonitorInfo))
        if monitor and user32.GetMonitorInfoW(monitor, ctypes.byref(info)):
            work = info.rcWork
            if work.right > work.left and work.bottom > work.top:
                return work.left, work.top, work.right, work.bottom
    except (AttributeError, OSError, TypeError, ValueError):
        pass
    return fallback


def fit_main_window_geometry(
    geometry: str, work: tuple[int, int, int, int], scale: float,
) -> tuple[str, tuple[int, int]]:
    """Bound client dimensions without reinterpreting Tk's signed position anchors."""
    left, top, right, bottom = work
    max_width = max(1, right - left - round(16 * scale))
    max_height = max(1, bottom - top - round(48 * scale))
    match = GEOMETRY_RE.fullmatch(geometry)
    width, height = (int(match[1]), int(match[2])) if match else (1280, 820)
    width, height = max(1, min(width, max_width)), max(1, min(height, max_height))
    position = (match[3] + match[4]) if match and match[3] is not None else ""
    return (f"{width}x{height}{position}",
            (min(round(980 * scale), max_width), min(round(620 * scale), max_height)))


def available_physical_memory_bytes() -> int:
    """Return currently available physical memory, or zero when unavailable."""

    if os.name != "nt":
        return 0

    class MemoryStatusEx(ctypes.Structure):
        _fields_ = [
            ("dwLength", ctypes.c_ulong),
            ("dwMemoryLoad", ctypes.c_ulong),
            ("ullTotalPhys", ctypes.c_ulonglong),
            ("ullAvailPhys", ctypes.c_ulonglong),
            ("ullTotalPageFile", ctypes.c_ulonglong),
            ("ullAvailPageFile", ctypes.c_ulonglong),
            ("ullTotalVirtual", ctypes.c_ulonglong),
            ("ullAvailVirtual", ctypes.c_ulonglong),
            ("ullAvailExtendedVirtual", ctypes.c_ulonglong),
        ]

    try:
        kernel32 = ctypes.WinDLL("kernel32", use_last_error=True)
        status = MemoryStatusEx(dwLength=ctypes.sizeof(MemoryStatusEx))
        kernel32.GlobalMemoryStatusEx.argtypes = [ctypes.POINTER(MemoryStatusEx)]
        kernel32.GlobalMemoryStatusEx.restype = ctypes.c_int
        if kernel32.GlobalMemoryStatusEx(ctypes.byref(status)):
            return int(status.ullAvailPhys)
    except (AttributeError, OSError, TypeError, ValueError):
        pass
    return 0


def icon_gallery_prefetch_capacity(
    item_count: int,
    *,
    available_memory: int,
) -> int:
    """Bound RAM-only speculative galleries while retaining a generous system reserve."""

    if item_count <= 0:
        return 0
    memory_slots = (
        max(0, available_memory - ICON_GALLERY_PREFETCH_MEMORY_RESERVE)
        // ICON_GALLERY_PREFETCH_MEMORY_PER_PACKAGE
        if available_memory > 0
        else min(item_count, 64)
    )
    return min(item_count, int(memory_slots))


def icon_gallery_blit_cache_limit(available_memory: int) -> int:
    """Give decoded lineup images half of safe headroom, bounded to 1 GiB."""

    if available_memory <= 0:
        return 128 * 1024**2
    headroom = max(0, available_memory - ICON_GALLERY_PREFETCH_MEMORY_RESERVE)
    return min(ICON_GALLERY_BLIT_CACHE_MAX_BYTES, headroom // 2)


# ==================== Tk application and orchestration ====================

type IconKey = tuple[str, int, str]  # package/style, pixel size, palette mode
type GalleryIconToken = tuple[int, int, str, int]  # generation, size, mode, revision
type GalleryIconEntry = tuple[GalleryIconToken, Any, bool]  # token, image, final artwork


class DecodedIconCache(MutableMapping[IconKey, Any]):
    """Own the decoded-artwork LRU and its estimated pixel-storage charge.

    All writes, replacements and removals update the same accounting. Tk widgets
    may retain images after eviction; this bounds cache ownership, not process RSS.
    This cache is used only on the GUI thread.
    """

    def __init__(self, entries: Iterable[tuple[IconKey, Any]] = ()) -> None:
        # Preserve existing recency when rekeying themes, including collisions.
        self._images: OrderedDict[IconKey, Any] = OrderedDict(entries)
        self.charge = sum(self.entry_charge(key) for key in self._images)
        self._trim()

    @staticmethod
    def entry_charge(key: IconKey) -> int:
        return 8 * key[1] ** 2 + 1024

    def __getitem__(self, key: IconKey) -> Any:
        return self._images[key]

    def __setitem__(self, key: IconKey, image: Any) -> None:
        if key not in self._images:
            self.charge += self.entry_charge(key)
        self._images[key] = image
        self._images.move_to_end(key)
        self._trim()

    def _trim(self) -> None:
        while self._images and (
            len(self._images) > DETAIL_ICON_MEMORY_LIMIT
            or self.charge > DETAIL_ICON_MEMORY_BUDGET_BYTES
        ):
            self.popitem(last=False)

    def __delitem__(self, key: IconKey) -> None:
        del self._images[key]
        self.charge -= self.entry_charge(key)

    def __iter__(self) -> Iterator[IconKey]:
        return iter(self._images)

    def __len__(self) -> int:
        return len(self._images)

    def move_to_end(self, key: IconKey) -> None:
        self._images.move_to_end(key)

    def popitem(self, last: bool = True) -> tuple[IconKey, Any]:
        key, image = self._images.popitem(last=last)
        self.charge -= self.entry_charge(key)
        return key, image

    def clear(self) -> None:
        self._images.clear()
        self.charge = 0


class WinDevPilotApp:
    def __init__(self, dpi_bootstrap: DpiBootstrapResult, *, debug_mode: bool = False) -> None:
        import tkinter as tk
        from tkinter import filedialog, messagebox, ttk

        self.tk = tk
        self.ttk = ttk
        self.filedialog = filedialog
        self.messagebox = messagebox
        self.debug_mode = debug_mode
        self._path_refresh_report = refresh_process_path_from_windows_environment()
        # Token elevation cannot change in-place for this process. Capture it
        # once so every row, confirmation, and worker describes the same
        # account context without repeatedly crossing the Win32 boundary.
        self.process_is_admin = is_admin()
        self.token_elevation_type = windows_token_elevation_type()
        self.root = tk.Tk()
        self.root.withdraw()
        self.root.title(f"{APP_NAME} {APP_VERSION}")
        self.ui_font_family, self.display_font_family = preferred_windows_ui_fonts(self.root)
        self.monospace_font_family = preferred_windows_monospace_font(self.root)
        self.visuals = WindowsVisualController(self.root, dpi_bootstrap)
        self.visuals.initialize()
        self.settings = SettingsStore()
        if self.settings.migrated_permission_hold_count:
            with contextlib.suppress(OSError):
                self.settings.save()
        geometry = str(self.settings.data.get("window_geometry", "1280x820"))
        try:
            stored_dpi = int(self.settings.data.get("window_geometry_dpi", 0))
        except (TypeError, ValueError):
            stored_dpi = 0
        restored_geometry = self.visuals.restore_geometry(geometry, stored_dpi)
        self.root.geometry(restored_geometry)
        self._fit_main_window(restored_geometry)
        self.providers = build_providers(debug_mode=debug_mode)
        self._provider_operation_locks = {
            key: threading.RLock() for key in self.providers
        }
        enabled_inventory_provider_keys = {
            key
            for key, provider in self.providers.items()
            if key != PORTABLE_PROVIDER_KEY
            and self.settings.data["providers"].get(key, provider.default_enabled)
        }
        self.installed_inventory = InstalledInventoryStore()
        self._update_release_observations = {
            key: dict(record)
            for key, record in self.installed_inventory.snapshot.update_observations.items()
        }
        self._installation_observations = {
            key: dict(record)
            for key, record in self.installed_inventory.snapshot.installation_observations.items()
        }
        self._observation_inventory_snapshot = self.installed_inventory.snapshot
        cached_installed_items = self.installed_inventory.items_for(
            enabled_inventory_provider_keys
        )
        self.items: dict[str, UpdateItem] = {}
        self._scan_view_items: dict[bool, dict[str, UpdateItem]] = {False: {}, True: {}}
        self._sort_state: tuple[str, bool] | None = None
        self._icon_sort_active = False
        self._icon_sort_grouped = False
        self._icon_sort_colors: dict[str, tuple[tuple, tuple[int, float, float]]] = {}
        self._icon_sort_refresh_pending = False
        self._icon_sort_refresh_after_id: str | None = None
        self._icon_color_working: int | None = None
        self.events: queue.Queue[tuple[str, Any]] = queue.Queue()
        self.cancel_requested = threading.Event()
        self._scan_cancel_requested = threading.Event()
        self.busy = False
        self._busy_kind = ""
        self._scan_active = False
        self._active_scan_owns_busy = False
        self._scan_progress_determinate = False
        self._scan_generation = 0
        self._active_scan_generation = 0
        self._active_scan_settings_snapshot: dict[str, Any] = {}
        self._active_scan_origin = ""
        self._scan_expected_provider_keys: set[str] = set()
        self._scan_current_provider_keys: set[str] = set()
        self._scan_provider_inventory_batches: dict[str, tuple[UpdateItem, ...]] = {}
        self._scan_windows_package_dates: dict[str, tuple[str, str]] = {}
        self._provisional_inventory_keys = {item.key for item in cached_installed_items}
        self._provisional_inventory_scanned_at = self.installed_inventory.snapshot.scanned_at
        self._installed_inventory_cache_write_active = False
        self._installed_inventory_cache_write_generation = 0
        self._provider_notice_seen: set[tuple[str, str, str]] = set()
        self._provider_duration_hints = {
            str(key): float(value)
            for key, value in self.settings.data.get("provider_duration_hints", {}).items()
            if key in self.providers and isinstance(value, (int, float))
        }
        self._provider_snapshot_refreshed_at: dict[str, float] = {}
        self.active_update_id = ""
        self.active_attempt_kind = ""
        self._elevated_batch_inflight = False
        self._active_operation_original_statuses: dict[str, str] = {}
        self._active_operation_results: list[dict[str, Any]] = []
        self._update_progress_completed_keys: set[str] = set()
        self._active_operation_items: dict[str, UpdateItem] = {}
        self._retryable_failure_candidate_keys: set[str] = set()
        self._pending_retry_selection_candidate_keys: set[str] = set()
        self._verification_results: dict[str, dict[str, Any]] = {}
        self._verification_update_id = ""
        self._post_update_refresh_outcomes: dict[str, str] = {}
        self._pending_suggested_install_history: dict[str, dict[str, str]] = {}
        self._tooltip_window: Any = None
        self._tooltip_key = ""
        self._tooltip_after_id: str | None = None
        self._tooltip_pending: tuple[str, str, int, int, int, int] | None = None
        self._hover_row = ""
        self._empty_state_message = ""
        self._quick_details_window: Any = None
        self._quick_details_refresh: Callable[[UpdateItem], None] | None = None
        self._icon_lineup_windows: dict[str, Any] = {}
        self._toolchain_health_window: Any = None
        self._toolchain_health_refresh: Callable[[], None] | None = None
        self._toolchain_health_generation = 0
        self._activity_base = "Idle - no package operation is running"
        self._activity_spinner_index = 0
        self._activity_after_id: str | None = None
        self._notification_after_id: str | None = None
        self._progress_after_id: str | None = None
        self._update_request_cue_after_id: str | None = None
        self._update_request_cue_until = 0.0
        self._nav_indicator_after_id: str | None = None
        self._busy_pulse_offset = 0
        self._rebuild_after_id: str | None = None
        self._rebuild_prime_cached_first_paint = False
        self._header_gradient_after_id: str | None = None
        self._accent_gradient_after_id: str | None = None
        self._main_splitter_sync_after_id: str | None = None
        self._main_splitter_drag_offset = 0
        self._poll_after_id: str | None = None
        self._ui_log_batch: list[str] | None = None
        self._event_poll_active = False
        self._theme_poll_after_id: str | None = None
        self._icon_renderer_warm_after_id: str | None = None
        self._initial_scan_after_id: str | None = None
        self._visual_diagnostics_after_id: str | None = None
        self._post_update_scan_after_id: str | None = None
        self._closing = False
        self._action_buttons: list[Any] = []
        self._update_selection_buttons: list[Any] = []
        self.secondary_actions_menu: Any | None = None
        self._secondary_action_entries: dict[str, int] = {}
        self._scan_results_current = False
        self._scan_refresh_reason = "No scan has completed yet"
        self._last_scan_completed_at: dt.datetime | None = None
        self._last_scan_duration_seconds = 0.0
        self._last_scan_delta: dict[str, int] = {}
        self._last_finish_scan_stage_ms: dict[str, float] = {}
        self._last_scan_all_packages = False
        self._package_gallery_mode = False
        self._package_gallery_after_id: str | None = None
        self._package_gallery_icons_after_id: str | None = None
        self._package_gallery_images: dict[str, GalleryIconEntry] = {}
        self._package_gallery_slots: dict[str, int] = {}
        self._package_gallery_pending: deque[str] = deque()
        self._package_gallery_attempts: dict[str, GalleryIconToken] = {}
        self._enrichment_generation = 0
        self._winget_enrichment_active = False
        self._date_sleuth_after_id: str | None = None
        self._date_sleuth_generation = 0
        self._date_sleuth_active = False
        self._date_sleuth_completed_signature = ""
        self._selection_touched_keys: set[str] = set()
        self._selection_block_notices: set[tuple[int, str]] = set()
        self._app_icon_image = self._create_app_icon_image()
        self._provider_icon_images: dict[tuple[str, int, str], tk.PhotoImage] = {}
        self._package_icon_images: dict[tuple[str, int, str], tk.PhotoImage] = {}
        self._details_icon_images = DecodedIconCache()
        self._compact_icon_images: dict[IconKey, Any] = {}
        self._compact_icon_tokens: dict[IconKey, GalleryIconToken] = {}
        self._package_icon_misses: set[tuple[str, int, str]] = set()
        self._package_icon_ready: set[tuple[str, int, str]] = set()
        self._item_icon_source_cache: dict[str, Path | None] = {}
        self._icon_source_target_px = max(48, self.visuals.px(DETAIL_ICON_SIZE_DIP))
        self._tree_icon_kind: dict[str, str] = {}
        self._icon_prepare_inflight: set[tuple[str, int, str]] = set()
        self._details_icon_callbacks: dict[tuple[str, int, str], list[Callable[[str], None]]] = {}
        self._details_refinement_listeners: list[Callable[[str], None]] = []
        self._icon_gallery_discovered = False
        self._icon_gallery_preparations: dict[str, dict[str, Any]] = {}
        self._icon_gallery_bundle_bytes = 0
        self._icon_gallery_bundle_report_threshold = ICON_GALLERY_MEMORY_REPORT_START
        self._icon_gallery_blit_cache: OrderedDict[
            tuple[bytes, int], tuple[Any, int]
        ] = OrderedDict()
        self._icon_gallery_blit_bytes = 0
        self._icon_gallery_blit_report_threshold = ICON_GALLERY_BLIT_MEMORY_REPORT_START
        self._icon_gallery_blit_warmup_announced = False
        self._icon_gallery_blit_limit = icon_gallery_blit_cache_limit(
            available_physical_memory_bytes()
        )
        self._icon_gallery_photo_decode_queue: deque[tuple[tuple[bytes, int], bytes]] = deque()
        self._icon_gallery_photo_decode_pending: set[tuple[bytes, int]] = set()
        self._icon_gallery_photo_decode_after_id: str | None = None
        self._icon_showcase_cache: OrderedDict[
            str, tuple[bytes, str, dict[str, Any]]
        ] = OrderedDict()
        self._icon_showcase_inflight: dict[str, list[Callable[..., None]]] = {}
        self._icon_gallery_inflight: dict[
            str, list[Callable[[IconGalleryMemoryBundle, str], None]]
        ] = {}
        self._icon_gallery_active_jobs = 0
        self._icon_gallery_job_sequence = 0
        self._icon_gallery_job_heap: list[tuple[int, int, str]] = []
        self._icon_gallery_queued_jobs: dict[
            str, tuple[int, int, Callable[[], None]]
        ] = {}
        self._icon_prepare_generation = 0
        self.icon_renderer = IconRenderCoordinator()
        self._lazy_icon_batch_active = False
        self._lazy_icon_batch_cached = 0
        self._lazy_icon_batch_failed = 0
        self._lazy_icon_batch_upscaled = 0
        self._lazy_icon_log_announced = False
        self._icon_hydration_after_id: str | None = None
        self._icon_key_release_after_id: str | None = None
        self._icon_memory_load_after_id: str | None = None
        self._icon_memory_priority_after_id: str | None = None
        self._icon_memory_load_queue: deque[tuple[str, int, str]] = deque()
        self._icon_memory_load_pending: set[tuple[str, int, str]] = set()
        self._icon_catalog_entries: dict[str, dict[str, Any]] = {}
        self._icon_catalog_blobs: dict[str, bytes] = {}
        self._icon_catalog_valid_paths: set[str] = set()
        self._icon_catalog_list_display_paths: dict[tuple[str, int], str] = {}
        self._icon_catalog_loaded = False
        self._icon_catalog_load_generation = 0
        self._icon_catalog_write_generation = 0
        self._icon_catalog_write_lock = threading.Lock()
        self._icon_catalog_write_active = False
        self._icon_catalog_write_pending = False
        self._icon_catalog_write_after_id: str | None = None
        self._icon_catalog_decode_after_id: str | None = None
        self._icon_catalog_decode_queue: deque[tuple[str, int, str]] = deque()
        self._icon_background_sweep_after_id: str | None = None
        self._icon_background_progress_after_id: str | None = None
        self._icon_background_sweep_queue: deque[str] = deque()
        self._icon_background_sweep_pending: set[str] = set()
        self._icon_background_sweep_active = False
        self._icon_background_sweep_total = 0
        self._details_background_after_id: str | None = None
        self._details_background_progress_after_id: str | None = None
        self._details_background_queue: deque[tuple[str, tuple[str, ...]]] = deque()
        self._details_background_active = False
        self._details_background_inflight = False
        self._details_background_generation = 0
        self._details_background_total = 0
        self._details_background_ready = 0
        self._details_background_failed = 0
        self._details_background_signature = ""
        self._details_background_completed_signature = ""
        self._details_background_completed_ready = 0
        self._details_background_completed_failed = 0
        self._icon_batch_finish_after_id: str | None = None
        self._icon_scroll_quiet_until = 0.0
        self._tree_hover_needs_refresh = False
        self._tree_wheel_remainder = 0
        self._tree_wheel_rows_per_notch = 0
        self._icon_resolution_generation = 0
        self._warm_icon_restore_generation = 0
        self._cache_clear_inflight = False
        self._diagnostic_bundle_inflight = False
        self._theme_toplevels: list[Any] = []
        self._theme_text_panels: list[Any] = []
        self._theme_listboxes: list[Any] = []
        self._theme_widgets: list[tuple[Any, dict[str, str]]] = []
        self._notification_level = "warning"
        self.logger = SessionLogger()
        self.logger.enable_fault_logging()
        if self.settings.migrated_permission_hold_count:
            self.logger.event(
                "legacy_winget_permission_holds_promoted",
                count=self.settings.migrated_permission_hold_count,
            )
        self._previous_threading_excepthook = threading.excepthook
        self._installed_threading_excepthook = self._report_thread_exception
        threading.excepthook = self._installed_threading_excepthook
        self.portable_inventory = PortableInventoryStore()
        cached_portables = tuple(
            portable_record_to_item(record) for record in self.portable_inventory.records()
        )
        self._scan_view_items[True] = {
            item.key: item for item in (*cached_installed_items, *cached_portables)
        }
        self._portable_scan_active = False
        self._portable_catalog_refresh_active = False
        self._portable_cache_verification_active = False
        self._portable_local_refresh_active = False
        self._portable_local_refresh_pending = False
        self._portable_local_refresh_completed = False
        self.root.report_callback_exception = self._report_tk_callback_exception
        self.logger.event(
            "session_start",
            application={"name": APP_NAME, "version": APP_VERSION},
            identity=process_identity_diagnostics(),
            working_directory=str(SCRIPT_PATH.parent),
            providers={
                key: {
                    "enabled": bool(
                        self.settings.data["providers"].get(key, provider.default_enabled)
                    ),
                    "available": provider.available(),
                    "executable": shutil.which(provider.executable) if provider.executable else "",
                }
                for key, provider in self.providers.items()
            },
            logging={
                "human_log": self.logger.path,
                "structured_trace": self.logger.trace_path,
                "fatal_fault_log": self.logger.crash_path,
                "redaction": "common credentials and current USERPROFILE path",
                "max_output_chars_per_process": MAX_DIAGNOSTIC_OUTPUT_CHARS,
            },
            portable_inventory={
                "cached_items": len(cached_portables),
                "roots": list(self.portable_inventory.roots()),
                "warning": self.portable_inventory.warning,
            },
            installed_inventory={
                "cached_items": len(cached_installed_items),
                "cached_providers": sorted(
                    {item.provider for item in cached_installed_items}
                ),
                "scanned_at": (
                    datetime_storage_timestamp(self._provisional_inventory_scanned_at)
                    if self._provisional_inventory_scanned_at is not None
                    else ""
                ),
                "warning": self.installed_inventory.warning,
                "lifecycle_observations": len(self._installation_observations),
            },
            path_recovery=dataclasses.asdict(self._path_refresh_report),
        )
        self.search_var = tk.StringVar()
        self.summary_var = tk.StringVar(value="Ready to scan")
        self.activity_var = tk.StringVar(value=self._activity_base)
        self.progress_var = tk.DoubleVar(value=0.0)
        self.palette = app_palette()
        self._client_animations_enabled = system_client_animations_enabled()
        self.visuals.set_dark_title_bars(self.palette["mode"] == "dark")
        self.visuals.set_chrome_colors(
            {key: value for key, value in self.palette.items() if key.startswith("chrome_")}
        )
        self._build_style()
        self._build_ui()
        if path_advisory := windows_path_refresh_advisory(self._path_refresh_report):
            self._append_log(f"PATH advisory: {path_advisory}")
            self._notify_user(
                path_advisory,
                level="warning",
                summary="Saved user PATH needs repair; this session recovered installed tools",
            )
        if self.portable_inventory.warning:
            self._append_log(
                f"Portable inventory cache warning: {self.portable_inventory.warning}"
            )
        elif cached_portables:
            self._append_log(
                f"Portable inventory: {len(cached_portables)} cached app(s) from "
                f"{len(self.portable_inventory.roots())} folder(s)"
            )
        if self.installed_inventory.warning:
            self._append_log(
                f"Previous installed inventory unavailable: {self.installed_inventory.warning}"
            )
        elif cached_installed_items:
            cached_time = (
                clock_display_time(
                    self._provisional_inventory_scanned_at,
                    twelve_hour=True,
                )
                if self._provisional_inventory_scanned_at is not None
                else "an earlier scan"
            )
            self._append_log(
                f"Previous installed inventory: {len(cached_installed_items)} package(s) "
                f"from {cached_time}; rows remain read-only until refreshed"
            )
        self.visuals.set_dpi_callback(self._apply_dpi_metrics)
        self._apply_dpi_metrics(self.visuals.current_dpi)
        self._apply_startup_view()
        self.search_var.trace_add("write", self._on_search_changed)
        self._update_search_clear_affordance()
        self.root.protocol("WM_DELETE_WINDOW", self._on_close)
        self._poll_after_id = self.root.after(100, self._poll_events)
        self._start_icon_catalog_load()
        self._theme_poll_after_id = self.root.after(WINDOWS_THEME_POLL_MS, self._poll_system_theme)
        self._icon_renderer_warm_after_id = self.root.after(
            ICON_RENDERER_WARM_DELAY_MS, self._warm_icon_renderer_idle
        )
        self._initial_scan_after_id = self.root.after(
            250, lambda: self._start_scan(origin="initial")
        )
        self.root.after(25, self._start_portable_cache_verification)
        self._visual_diagnostics_after_id = self.root.after(250, self._report_visual_diagnostics)
        self.visuals.prepare_first_show()
        self._resize_hold: WindowsResizeHold | None = None
        if os.environ.get("WINDEVPILOT_RESIZE_HOLD", "1") != "0":
            self._resize_hold = WindowsResizeHold(
                self.root, (self.accent_canvas, self.outer),
                report_error=lambda error: self.logger.event("resize_hold_disabled", error=error),
            )
            self._resize_hold.install()
        self.root.deiconify()
        self.root.after_idle(self._focus_startup_search)

    def _report_tk_callback_exception(
        self, exc_type: Any, exc_value: BaseException, exc_traceback: Any
    ) -> None:
        """Make otherwise-invisible Tk callback failures diagnosable in windowless mode."""

        exception_name = getattr(exc_type, "__name__", str(exc_type))
        trace_text = "".join(traceback.format_exception(exc_type, exc_value, exc_traceback))
        self.logger.event(
            "tk_callback_exception",
            exception_type=exception_name,
            error=str(exc_value),
            traceback=bounded_diagnostic_output(trace_text),
        )
        if self._closing or not hasattr(self, "log_text"):
            return
        try:
            self._notify_user(
                f"An internal interface callback failed: {exception_name}: {exc_value}",
                level="error",
                summary="Internal interface error; details were logged",
            )
        except Exception:
            # Never let the reporting hook recursively invoke itself.
            return

    def _report_thread_exception(self, args: Any) -> None:
        """Persist otherwise-invisible background-thread failures."""

        exception_name = getattr(args.exc_type, "__name__", str(args.exc_type))
        trace_text = "".join(
            traceback.format_exception(args.exc_type, args.exc_value, args.exc_traceback)
        )
        with contextlib.suppress(Exception):
            self.logger.event(
                "worker_thread_exception",
                thread=getattr(args.thread, "name", ""),
                exception_type=exception_name,
                error=str(args.exc_value),
                traceback=bounded_diagnostic_output(trace_text),
            )

    def _start_guarded_worker(
        self,
        target: Callable[[], None],
        *,
        name: str,
        operation: str,
        generation: int = 0,
    ) -> None:
        """Run a state-owning worker and always report an unexpected terminal failure."""

        def guarded() -> None:
            try:
                target()
            except Exception as exc:
                try:
                    trace_text = "".join(
                        traceback.format_exception(type(exc), exc, exc.__traceback__)
                    )
                except Exception:
                    trace_text = f"{type(exc).__name__}: {exc}"
                payload = {
                    "operation": operation,
                    "generation": generation,
                    "thread": name,
                    "exception_type": type(exc).__name__,
                    "error": str(exc),
                    "traceback": bounded_diagnostic_output(trace_text),
                }
                with contextlib.suppress(Exception):
                    self.logger.event("state_worker_failed", **payload)
                self.events.put(("worker_failed", payload))

        threading.Thread(target=guarded, name=name, daemon=True).start()

    def _finish_worker_failure(self, payload: Mapping[str, Any]) -> None:
        """Release UI state after a guarded worker dies before its normal terminal event."""

        operation = str(payload.get("operation", "background operation"))
        generation = int(payload.get("generation", 0) or 0)
        if (
            operation == "scan"
            and generation
            and generation != self._active_scan_generation
        ):
            return
        if operation == "cache-clear":
            self._cache_clear_inflight = False
        if operation == "diagnostic-bundle":
            self._diagnostic_bundle_inflight = False
            if self.bundle_button is not None:
                self.bundle_button.configure(state="disabled" if self.busy else "normal")
        if operation == "portable-scan":
            self._portable_scan_active = False
        if operation == "scan":
            scan_owned_busy = self._active_scan_owns_busy
            self._scan_active = False
            self._active_scan_owns_busy = False
            self._scan_cancel_requested.clear()
            if scan_owned_busy and self.busy and self._busy_kind == "scan":
                self.progress.stop()
                self.progress.configure(mode="determinate")
                self._set_progress_value(0, animate=False)
                self._set_busy(False)
            else:
                self._refresh_scan_button_style()
        expected_busy_kind = {
            "portable-scan": "portable-scan",
            "update": "update",
            "uninstall": "uninstall",
            "suggested-install": "install",
            "selected-preflight": "selected-preflight",
        }.get(operation)
        if expected_busy_kind and self.busy and self._busy_kind == expected_busy_kind:
            self.progress.stop()
            self.progress.configure(mode="determinate")
            self._set_progress_value(0, animate=False)
            self._set_busy(False)
            self.cancel_requested.clear()
        if operation in {"update", "uninstall", "suggested-install"}:
            self._elevated_batch_inflight = False
            operation_id = self.active_update_id
            partial_results = list(self._active_operation_results)
            remembered_results = 0
            if operation == "update" and partial_results:
                try:
                    self._remember_attempt_outcomes(partial_results)
                    remembered_results = len(partial_results)
                except Exception as exc:
                    self.logger.event(
                        "mutation_worker_partial_history_failed",
                        operation=operation,
                        operation_id=operation_id,
                        error=f"{type(exc).__name__}: {exc}",
                    )
            restored_statuses = 0
            for key, original_status in self._active_operation_original_statuses.items():
                item = self._scan_view_item(key)
                if item is None or item.status not in TRANSIENT_OPERATION_STATUSES:
                    continue
                self._set_scan_view_item_status(key, original_status)
                restored_statuses += 1
            self._active_operation_original_statuses.clear()
            self._active_operation_results.clear()
            self._active_operation_items.clear()
            self.active_update_id = ""
            self.active_attempt_kind = ""
            self._mark_scan_refresh_needed(
                "A package operation stopped after an internal error; rescan to confirm actual state"
            )
            self.logger.event(
                "mutation_worker_failure_cleanup",
                operation=operation,
                operation_id=operation_id,
                restored_status_count=restored_statuses,
                remembered_result_count=remembered_results,
            )
        if operation in {"scan", "portable-scan"}:
            self._mark_scan_refresh_needed(
                "A scan stopped after an internal error; run Scan again"
            )
        label = operation.replace("-", " ")
        self._notify_user(
            f"The {label} stopped after an internal error: "
            f"{payload.get('exception_type', 'Error')}: {payload.get('error', '')}",
            level="error",
            summary=f"{label.title()} stopped unexpectedly; details were logged",
        )

    def _ui_font(
        self, size: int, *, semibold: bool = False, display: bool = False
    ) -> tuple[Any, ...]:
        family = self.display_font_family if display else self.ui_font_family
        return (family, size, "bold") if semibold else (family, size)

    def _mono_font(self, size: int, *, semibold: bool = False) -> tuple[Any, ...]:
        return (
            (self.monospace_font_family, size, "bold")
            if semibold
            else (self.monospace_font_family, size)
        )

    def _build_style(self) -> None:
        if hold := getattr(self, "_resize_hold", None):
            hold.suspend()
        self.style = self.ttk.Style(self.root)
        if self.palette["mode"] == "dark" and "clam" in self.style.theme_names():
            self.style.theme_use("clam")
        elif "vista" in self.style.theme_names():
            self.style.theme_use("vista")
        self.root.configure(background=self.palette["window"])
        self.style.configure(".", font=self._ui_font(10))
        self.style.configure("TFrame", background=self.palette["window"])
        self.style.configure("Surface.TFrame", background=self.palette["surface"])
        self.style.configure(
            "TLabel",
            background=self.palette["window"],
            foreground=self.palette["text"],
        )
        self.style.configure(
            "TButton",
            background=self.palette["button"],
            foreground=self.palette["text"],
            bordercolor=self.palette["border"],
            lightcolor=self.palette["button"],
            darkcolor=self.palette["button"],
            focuscolor=self.palette["accent"],
            padding=(6, 3),
        )
        self.style.map(
            "TButton",
            background=[
                ("active", self.palette["button_active"]),
                ("pressed", self.palette["surface_alt"]),
                ("disabled", self.palette["button_disabled"]),
                ("!disabled", self.palette["button"]),
            ],
            foreground=[
                ("disabled", self.palette["disabled_text"]),
                ("!disabled", self.palette["text"]),
            ],
        )
        self.style.configure(
            "SecondaryActions.TMenubutton",
            background=self.palette["button"],
            foreground=self.palette["text"],
            bordercolor=self.palette["border"],
            lightcolor=self.palette["button"],
            darkcolor=self.palette["button"],
            arrowcolor=self.palette["text_soft"],
            focuscolor=self.palette["accent"],
            padding=(6, 3),
        )
        self.style.map(
            "SecondaryActions.TMenubutton",
            background=[
                ("active", self.palette["button_active"]),
                ("pressed", self.palette["surface_alt"]),
                ("disabled", self.palette["button_disabled"]),
                ("!disabled", self.palette["button"]),
            ],
            foreground=[
                ("disabled", self.palette["disabled_text"]),
                ("!disabled", self.palette["text"]),
            ],
            arrowcolor=[
                ("disabled", self.palette["disabled_text"]),
                ("!disabled", self.palette["text_soft"]),
            ],
        )
        self.style.configure(
            "TEntry",
            fieldbackground=self.palette["surface"],
            foreground=self.palette["text"],
            insertcolor=self.palette["text"],
            bordercolor=self.palette["entry_border"],
        )
        self.style.map(
            "TEntry",
            fieldbackground=[
                ("disabled", self.palette["button_disabled"]),
                ("!disabled", self.palette["surface"]),
            ],
            foreground=[
                ("disabled", self.palette["disabled_text"]),
                ("!disabled", self.palette["text"]),
            ],
        )
        self.style.configure(
            "TPanedwindow",
            background=self.palette["window"],
            bordercolor=self.palette["border"],
        )
        self.style.configure(
            "Sash",
            background=self.palette["border"],
            sashthickness=4,
        )
        self.style.configure(
            "TScrollbar",
            background=self.palette["scrollbar"],
            troughcolor=self.palette["scrollbar_trough"],
            bordercolor=self.palette["border"],
            arrowcolor=self.palette["text_soft"],
            lightcolor=self.palette["scrollbar"],
            darkcolor=self.palette["scrollbar"],
        )
        self.style.map(
            "TScrollbar",
            background=[
                ("active", self.palette["scrollbar_active"]),
                ("pressed", self.palette["scrollbar_active"]),
                ("!disabled", self.palette["scrollbar"]),
            ],
            arrowcolor=[
                ("disabled", self.palette["disabled_text"]),
                ("!disabled", self.palette["text_soft"]),
            ],
        )
        self.style.configure(
            "TProgressbar",
            background=self.palette["progress"],
            troughcolor=self.palette["progress_trough"],
            bordercolor=self.palette["border"],
            lightcolor=self.palette["progress"],
            darkcolor=self.palette["progress"],
        )
        self.style.configure(
            "Horizontal.TProgressbar",
            background=self.palette["progress"],
            troughcolor=self.palette["progress_trough"],
            bordercolor=self.palette["border"],
            lightcolor=self.palette["progress"],
            darkcolor=self.palette["progress"],
        )
        self.style.configure(
            "Subtitle.TLabel",
            background=self.palette["window"],
            foreground=self.palette["text_soft"],
        )
        self.style.configure(
            "Body.TLabel",
            background=self.palette["window"],
            foreground=self.palette["text_secondary"],
            font=self._ui_font(10),
        )
        self.style.configure(
            "Treeview",
            rowheight=self.visuals.px(UPDATE_ROW_HEIGHT_DIP),
            font=self._ui_font(10),
            background=self.palette["surface"],
            fieldbackground=self.palette["surface"],
            foreground=self.palette["text"],
            bordercolor=self.palette["border"],
            lightcolor=self.palette["surface"],
            darkcolor=self.palette["surface"],
        )
        self.style.map(
            "Treeview",
            background=[("selected", self.palette["accent"])],
            foreground=[("selected", self.palette["accent_text"])],
        )
        self.style.configure(
            "Treeview.Heading",
            font=self._ui_font(10, semibold=True),
            foreground=self.palette["text"],
            background=self.palette["surface_alt"],
            bordercolor=self.palette["border"],
            lightcolor=self.palette["surface_alt"],
            darkcolor=self.palette["surface_alt"],
        )
        self.style.map(
            "Treeview.Heading",
            background=[("active", self.palette["button_active"])],
            foreground=[("!disabled", self.palette["text"])],
        )
        self.style.configure(
            "Accent.TButton",
            font=self._ui_font(10, semibold=True),
            background=self.palette["button"],
            foreground=self.palette["accent"],
        )
        self.style.map(
            "Accent.TButton",
            background=[
                ("active", self.palette["button_active"]),
                ("disabled", self.palette["button_disabled"]),
                ("!disabled", self.palette["button"]),
            ],
            foreground=[
                ("disabled", self.palette["disabled_text"]),
                ("!disabled", self.palette["accent"]),
            ],
        )
        self.style.configure(
            "PrimaryNav.TButton",
            font=self._ui_font(11, semibold=True),
            padding=(10, 5),
            background=self.palette["button"],
            foreground=self.palette["text"],
        )
        self.style.map(
            "PrimaryNav.TButton",
            background=[
                ("active", self.palette["button_active"]),
                ("disabled", self.palette["button_disabled"]),
                ("!disabled", self.palette["button"]),
            ],
            foreground=[
                ("disabled", self.palette["disabled_text"]),
                ("!disabled", self.palette["text"]),
            ],
        )
        self.style.configure(
            "PrimaryNavActive.TButton",
            font=self._ui_font(11, semibold=True),
            padding=(10, 5),
            background=self.palette["button"],
            foreground=self.palette["accent"],
        )
        self.style.map(
            "PrimaryNavActive.TButton",
            background=[
                ("active", self.palette["button_active"]),
                ("disabled", self.palette["button_disabled"]),
                ("!disabled", self.palette["button"]),
            ],
            foreground=[
                ("disabled", self.palette["disabled_text"]),
                ("!disabled", self.palette["accent"]),
            ],
        )
        self.style.configure(
            "ScanFresh.TButton",
            font=self._ui_font(11, semibold=True),
            padding=(10, 5),
            background=self.palette["button"],
            foreground=self.palette["scan_fresh"],
        )
        self.style.map(
            "ScanFresh.TButton",
            background=[
                ("active", self.palette["button_active"]),
                ("disabled", self.palette["button_disabled"]),
                ("!disabled", self.palette["button"]),
            ],
            foreground=[
                ("disabled", self.palette["disabled_text"]),
                ("!disabled", self.palette["scan_fresh"]),
            ],
        )
        self.style.configure(
            "ScanStale.TButton",
            font=self._ui_font(11, semibold=True),
            padding=(10, 5),
            background=self.palette["button"],
            foreground=self.palette["scan_stale"],
        )
        self.style.map(
            "ScanStale.TButton",
            background=[
                ("active", self.palette["button_active"]),
                ("disabled", self.palette["button_disabled"]),
                ("!disabled", self.palette["button"]),
            ],
            foreground=[
                ("disabled", self.palette["disabled_text"]),
                ("!disabled", self.palette["scan_stale"]),
            ],
        )

    def _poll_system_theme(self) -> None:
        """Follow Windows' app-theme preference without disturbing active work."""

        self._theme_poll_after_id = None
        if self._closing:
            return
        if self._native_window_interaction_active():
            self._theme_poll_after_id = self.root.after(
                WINDOW_DRAG_BUSY_ANIMATION_POLL_MS, self._poll_system_theme
            )
            return
        try:
            requested_mode = windows_app_theme_mode()
            if requested_mode is not None and requested_mode != self.palette["mode"]:
                self._apply_live_theme(requested_mode)
            animations_enabled = system_client_animations_enabled()
            if animations_enabled != self._client_animations_enabled:
                self._client_animations_enabled = animations_enabled
                self._draw_accent_gradient()
        finally:
            if not self._closing:
                self._theme_poll_after_id = self.root.after(
                    WINDOWS_THEME_POLL_MS, self._poll_system_theme
                )

    def _warm_icon_renderer_idle(self) -> None:
        """Pre-start the windowless icon child off Tk's thread after startup settles."""

        self._icon_renderer_warm_after_id = None
        if self._closing:
            return
        generation = self._icon_prepare_generation
        threading.Thread(
            target=lambda: self.icon_renderer.warm(generation),
            name="wdp-icon-renderer-warm",
            daemon=True,
        ).start()

    def _apply_live_theme(self, mode: str) -> None:
        if mode == self.palette["mode"]:
            return
        previous_mode = self.palette["mode"]
        self._hide_tooltip()
        self.palette = palette_for_mode(mode)
        self.visuals.set_dark_title_bars(mode == "dark")
        self.visuals.set_chrome_colors(
            {key: value for key, value in self.palette.items() if key.startswith("chrome_")}
        )
        self._build_style()
        self._refresh_registered_theme_widgets()

        self._cancel_after_id("_header_gradient_after_id")
        self._cancel_after_id("_accent_gradient_after_id")
        self._header_gradient_key = None
        self._accent_gradient_key = None
        self._main_splitter_gradient_key = None
        self.header_canvas.configure(background=self.palette["surface"])
        self.header_canvas.itemconfigure(self.header_title_id, fill=self.palette["title"])
        self.accent_canvas.configure(background=self.palette["accent"])
        if hasattr(self, "main_splitter"):
            self.main_splitter.configure(background=self.palette["header_mid"])
            self._draw_main_splitter_gradient()
        self._draw_header_gradient()
        self._draw_accent_gradient()
        for tag, role in (
            ("selected", "selected"),
            ("review", "review"),
            ("admin", "admin"),
            ("hover", "hover"),
        ):
            self.tree.tag_configure(tag, background=self.palette[role])

        if self.busy:
            self.activity_label.configure(
                background=self.palette["busy_soft"], foreground=self.palette["busy_text"]
            )
        else:
            self.activity_label.configure(
                background=self.palette["idle"], foreground=self.palette["idle_text"]
            )
        if self.notification_label.winfo_manager():
            is_error = self._notification_level == "error"
            self.notification_label.configure(
                background=self.palette["danger_surface" if is_error else "busy_soft"],
                foreground=self.palette["danger_text" if is_error else "busy_text"],
            )

        # Generated app PNGs are palette-neutral, so retain their decoded
        # PhotoImages under the new mode key. Only provider dots need repainting.
        self._reset_ready_icon_memory_load()
        self._provider_icon_images = {
            (style, size, mode if palette_mode == previous_mode else palette_mode): image
            for (style, size, palette_mode), image in self._provider_icon_images.items()
        }
        getattr(self, "_compact_icon_images", {}).clear()
        getattr(self, "_compact_icon_tokens", {}).clear()
        self._package_icon_images = {
            (item_key, size, mode if palette_mode == previous_mode else palette_mode): image
            for (item_key, size, palette_mode), image in self._package_icon_images.items()
        }
        self._details_icon_images = DecodedIconCache(
            (
                (item_key, size, mode if palette_mode == previous_mode else palette_mode),
                image,
            )
            for (item_key, size, palette_mode), image in self._details_icon_images.items()
        )
        self._package_icon_misses = {
            (item_key, size, mode if palette_mode == previous_mode else palette_mode)
            for item_key, size, palette_mode in self._package_icon_misses
        }
        self._package_icon_ready = {
            (item_key, size, mode if palette_mode == previous_mode else palette_mode)
            for item_key, size, palette_mode in self._package_icon_ready
        }
        self._queue_resident_compact_icons()
        for row in self.tree.get_children():
            item = self.items.get(str(row))
            if item is None or self._tree_icon_kind.get(str(row)) == "app":
                continue
            with contextlib.suppress(Exception):
                getattr(self, "_tree_row_presentations", {}).pop(row, None)
                self.tree.item(row, image=self._fallback_icon(item), text="")
                self._tree_icon_kind[str(row)] = "provider"
        if self.items:
            self._reset_background_details_icon_sweep()
            self._start_warm_icon_cache_restore()
            self._schedule_visible_icon_hydration(delay_ms=0, restart=True)
        self._refresh_scan_view_mode_controls()

        self._schedule_package_gallery_render()
        self.logger.event("theme_changed", mode=mode, source="Windows app theme")
        self._append_log(
            f"Interface theme changed to {mode} to follow Windows",
            show_in_ui=False,
        )

    def _cancel_after_id(self, attr_name: str) -> None:
        after_id = getattr(self, attr_name, None)
        if after_id is None:
            return
        with contextlib.suppress(Exception):
            self.root.after_cancel(after_id)
        setattr(self, attr_name, None)

    def _button(
        self, parent: Any, *, tooltip: str, busy_disabled: bool = False, **kwargs: Any
    ) -> Any:
        button = self.ttk.Button(parent, **kwargs)
        self._bind_widget_tooltip(button, tooltip)
        if busy_disabled:
            self._action_buttons.append(button)
        return button

    def _create_app_icon_image(self) -> Any | None:
        try:
            size = 64
            image = self.tk.PhotoImage(width=size, height=size)
            for y, row in enumerate(generated_app_icon_rows(size)):
                colors = []
                for index in range(0, len(row), 4):
                    red, green, blue, _alpha = row[index : index + 4]
                    colors.append(f"#{red:02x}{green:02x}{blue:02x}")
                image.put("{" + " ".join(colors) + "}", to=(0, y))
            self.root.iconphoto(True, image)
            return image
        except Exception:
            return None

    @staticmethod
    def _close_toplevel_from_escape(window: Any, event: Any) -> str:
        """Close one secondary window, after first leaving an active text editor."""

        widget = getattr(event, "widget", None)
        if widget is not None and widget is not window:
            try:
                widget_class = str(widget.winfo_class())
            except Exception:
                widget_class = ""
            if widget_class in {
                "Entry",
                "TEntry",
                "Text",
                "Spinbox",
                "TSpinbox",
                "TCombobox",
            }:
                try:
                    state = str(widget.cget("state")).casefold()
                except Exception:
                    state = "normal"
                if state != "disabled":
                    # Preserve edits. The first Escape leaves the editor; a second
                    # Escape, now owned by the dialog itself, closes the window.
                    with contextlib.suppress(Exception):
                        window.focus_set()
                    return "break"
        with contextlib.suppress(Exception):
            window.destroy()
        return "break"

    def _create_toplevel(self, parent: Any, *, background: str | None = None) -> Any:
        """Build off-screen; apply layout/chrome before the first visible frame."""
        window = self.tk.Toplevel(parent, background=background or self.palette["window"])
        window.withdraw()
        window._wdp_fixed_background = background
        self._configure_toplevel(window)
        self.visuals.register_toplevel(window)

        def present() -> None:
            if self._closing or not window.winfo_exists():
                return
            # A timer, not after_idle: callers sometimes drain idle geometry work
            # while assembling content. That must not reveal a partial dialog.
            window.update_idletasks()
            if self._closing or not window.winfo_exists():
                return
            self.visuals.prepare_first_show(window)
            window.deiconify()
            window.lift()
            window.focus_set()

        window.after(0, present)
        return window

    def _configure_toplevel(self, window: Any) -> None:
        if not any(existing is window for existing in self._theme_toplevels):
            self._theme_toplevels.append(window)
        if self._app_icon_image is not None:
            with contextlib.suppress(Exception):
                window.iconphoto(False, self._app_icon_image)
        if not getattr(window, "_wdp_escape_bound", False):
            window.bind(
                "<Escape>",
                lambda event, target=window: self._close_toplevel_from_escape(
                    target, event
                ),
                add="+",
            )
            window._wdp_escape_bound = True

    def _configure_text_panel(self, text: Any, *, allow_clear: bool = False) -> None:
        if not any(existing is text for existing in self._theme_text_panels):
            self._theme_text_panels.append(text)
        text.configure(
            background=self.palette["text_panel"],
            foreground=self.palette["text"],
            insertbackground=self.palette["text"],
            selectbackground=self.palette["accent"],
            selectforeground=self.palette["accent_text"],
            highlightbackground=self.palette["border"],
            highlightcolor=self.palette["accent"],
        )
        if not getattr(text, "_wdp_context_menu_bound", False):
            self._bind_text_context_menu(text, allow_clear=allow_clear)
            text._wdp_context_menu_bound = True

    def _configure_listbox(self, listbox: Any) -> None:
        if not any(existing is listbox for existing in self._theme_listboxes):
            self._theme_listboxes.append(listbox)
        listbox.configure(
            background=self.palette["text_panel"],
            foreground=self.palette["text"],
            selectbackground=self.palette["accent"],
            selectforeground=self.palette["accent_text"],
            highlightbackground=self.palette["border"],
            highlightcolor=self.palette["accent"],
        )
        if not getattr(listbox, "_wdp_context_menu_bound", False):
            self._bind_listbox_context_menu(listbox)
            listbox._wdp_context_menu_bound = True

    def _register_theme_widget(self, widget: Any, **option_roles: str) -> None:
        """Track raw Tk widgets whose colors ttk cannot restyle globally."""

        self._theme_widgets.append((widget, dict(option_roles)))
        widget.configure(**{option: self.palette[role] for option, role in option_roles.items()})

    @staticmethod
    def _live_widgets(widgets: Sequence[Any]) -> list[Any]:
        live: list[Any] = []
        for widget in widgets:
            try:
                if widget.winfo_exists():
                    live.append(widget)
            except Exception:
                continue
        return live

    def _refresh_registered_theme_widgets(self) -> None:
        live_roles: list[tuple[Any, dict[str, str]]] = []
        for widget, option_roles in self._theme_widgets:
            try:
                if not widget.winfo_exists():
                    continue
                widget.configure(
                    **{option: self.palette[role] for option, role in option_roles.items()}
                )
                live_roles.append((widget, option_roles))
            except Exception:
                continue
        self._theme_widgets = live_roles

        self._theme_text_panels = self._live_widgets(self._theme_text_panels)
        for text in self._theme_text_panels:
            with contextlib.suppress(Exception):
                self._configure_text_panel(text)
                self._configure_log_tags(text)
                self._configure_health_tags(text)

        self._theme_listboxes = self._live_widgets(self._theme_listboxes)
        for listbox in self._theme_listboxes:
            with contextlib.suppress(Exception):
                self._configure_listbox(listbox)

        self._theme_toplevels = self._live_widgets(self._theme_toplevels)
        for window in self._theme_toplevels:
            with contextlib.suppress(Exception):
                window.configure(background=getattr(window, "_wdp_fixed_background", None) or self.palette["window"])
                self.visuals.register_toplevel(window)

    def _provider_toggle_row(
        self,
        parent: Any,
        *,
        label: str,
        variable: Any,
        available: bool,
        read_only: bool,
        command: Any,
        tooltip: str,
    ) -> Any:
        tk = self.tk
        px = self.visuals.px
        row = tk.Frame(parent, bd=0, highlightthickness=0)
        enabled = bool(available and not read_only)
        glyph = tk.Label(
            row,
            text=CHECKED_GLYPH if bool(variable.get()) else UNCHECKED_GLYPH,
            width=2,
            anchor="w",
            font=PROVIDER_TOGGLE_GLYPH_FONT,
        )
        text = tk.Label(
            row,
            text=label,
            anchor="w",
            font=self._ui_font(11),
        )
        foreground_role = "text" if enabled else "disabled_text"
        self._register_theme_widget(row, background="window")
        self._register_theme_widget(glyph, background="window", foreground=foreground_role)
        self._register_theme_widget(text, background="window", foreground=foreground_role)
        glyph.pack(side="left", padx=(0, px(6)))
        text.pack(side="left", fill="x", expand=True)

        def refresh() -> None:
            glyph.configure(text=CHECKED_GLYPH if bool(variable.get()) else UNCHECKED_GLYPH)

        def toggle(_event: Any = None) -> str:
            if not enabled:
                return "break"
            variable.set(not bool(variable.get()))
            refresh()
            command()
            return "break"

        if enabled:
            for widget in (row, glyph, text):
                widget.configure(cursor="hand2")
                widget.bind("<Button-1>", toggle, add="+")
                widget.bind("<space>", toggle, add="+")
        self._bind_widget_tooltip(row, tooltip)
        self._bind_widget_tooltip(glyph, tooltip)
        self._bind_widget_tooltip(text, tooltip)
        return row

    def _clipboard_set_silent(self, value: str) -> None:
        if not value:
            return
        self._set_clipboard(value)

    def _set_clipboard(self, value: str) -> bool:
        """Write text without letting a transient Windows clipboard lock escape."""

        try:
            self.root.clipboard_clear()
            self.root.clipboard_append(value)
            self.root.update_idletasks()
        except self.tk.TclError as exc:
            self.logger.event(
                "clipboard_write_failed",
                error=f"{type(exc).__name__}: {exc}",
            )
            self._notify_user(
                "The Windows clipboard is busy. Nothing was copied; try again.",
                level="warning",
                summary="Clipboard busy — copy did not complete",
            )
            return False
        return True

    def _bind_text_context_menu(self, text: Any, *, allow_clear: bool = False) -> None:
        tk = self.tk

        def selected_text() -> str:
            try:
                return str(text.get("sel.first", "sel.last"))
            except Exception:
                return ""

        def all_text() -> str:
            try:
                return str(text.get("1.0", "end-1c"))
            except Exception:
                return ""

        def clear_text() -> None:
            try:
                previous_state = str(text.cget("state"))
                if previous_state == "disabled":
                    text.configure(state="normal")
                text.delete("1.0", "end")
                if previous_state == "disabled":
                    text.configure(state="disabled")
            except Exception:
                return

        def show_menu(event: Any) -> str:
            menu = tk.Menu(text, tearoff=False)
            selection = selected_text()
            contents = all_text()
            menu.add_command(
                label="Copy selection",
                command=lambda: self._clipboard_set_silent(selection),
                state="normal" if selection else "disabled",
            )
            menu.add_command(
                label="Copy all",
                command=lambda: self._clipboard_set_silent(contents),
                state="normal" if contents else "disabled",
            )
            if allow_clear:
                menu.add_separator()
                menu.add_command(
                    label="Clear",
                    command=clear_text,
                    state="normal" if contents else "disabled",
                )
            menu.tk_popup(event.x_root, event.y_root)
            menu.grab_release()
            return "break"

        text.bind("<Button-3>", show_menu, add="+")

    def _bind_listbox_context_menu(self, listbox: Any) -> None:
        tk = self.tk

        def selected_rows() -> str:
            try:
                return "\n".join(str(listbox.get(index)) for index in listbox.curselection())
            except Exception:
                return ""

        def all_rows() -> str:
            try:
                return "\n".join(str(listbox.get(index)) for index in range(listbox.size()))
            except Exception:
                return ""

        def show_menu(event: Any) -> str:
            row = listbox.nearest(event.y)
            if 0 <= row < listbox.size() and row not in listbox.curselection():
                listbox.selection_clear(0, "end")
                listbox.selection_set(row)
                listbox.activate(row)
            selected = selected_rows()
            menu = tk.Menu(listbox, tearoff=False)
            populate = getattr(listbox, "_wdp_populate_context_menu", None)
            custom_items_added = bool(populate(menu)) if callable(populate) else False
            if custom_items_added:
                menu.add_separator()
            menu.add_command(
                label="Copy selected",
                command=lambda: self._clipboard_set_silent(selected),
                state="normal" if selected else "disabled",
            )
            menu.add_command(
                label="Copy all",
                command=lambda: self._clipboard_set_silent(all_rows()),
                state="normal" if all_rows() else "disabled",
            )
            menu.tk_popup(event.x_root, event.y_root)
            menu.grab_release()
            return "break"

        listbox.bind("<Button-3>", show_menu, add="+")

    def _configure_log_tags(self, text: Any) -> None:
        text.tag_configure("log_success", foreground=self.palette["log_success"])
        text.tag_configure("log_warning", foreground=self.palette["log_warning"])
        text.tag_configure("log_failure", foreground=self.palette["log_failure"])
        text.tag_configure("log_info", foreground=self.palette["log_info"])
        text.tag_configure("log_dim", foreground=self.palette["log_dim"])

    def _configure_health_tags(self, text: Any) -> None:
        text.tag_configure(
            "health_title", font=self._ui_font(12, semibold=True), foreground=self.palette["title"]
        )
        text.tag_configure(
            "health_ok",
            font=self._mono_font(9, semibold=True),
            foreground=self.palette["log_success"],
        )
        text.tag_configure(
            "health_warn",
            font=self._mono_font(9, semibold=True),
            foreground=self.palette["log_warning"],
        )
        text.tag_configure(
            "health_error",
            font=self._mono_font(9, semibold=True),
            foreground=self.palette["log_failure"],
        )
        text.tag_configure("health_label", font=self._mono_font(9, semibold=True))
        text.tag_configure("health_dim", foreground=self.palette["log_dim"])
        text.tag_configure("health_path", foreground=self.palette["health_path"])
        text.tag_configure("health_command", foreground=self.palette["health_command"])

    def _provider_tooltip(self, provider_key: str, label: str, *, available: bool) -> str:
        availability = (
            "This provider is installed and can be scanned."
            if available
            else "This provider was not found on PATH, so it cannot be enabled here."
        )
        if provider_key == "winget":
            detail = (
                "WinGet scans its community catalog for per-user and machine-wide "
                "desktop packages. Microsoft Store inventory is shown separately."
            )
        elif provider_key == MICROSOFT_STORE_PROVIDER_KEY:
            detail = (
                "Microsoft Store scans Store-signed apps, games, and components registered "
                "to the launching Windows account. Exact catalog IDs update selectively "
                "through WinGet's msstore source; other entries can open the Store updates "
                "page. This provider never elevates into another account."
            )
        elif provider_key == "scoop":
            detail = "Scoop scans and updates current-user bucket apps and command-line tools."
        elif provider_key == "chocolatey":
            detail = (
                "Chocolatey scans machine-wide packages and usually needs administrator "
                "rights to update them."
            )
        elif provider_key == "pip":
            detail = (
                "pip scans the current user's global Python package site. It is off by "
                "default because bulk pip updates can trigger dependency conflicts; "
                "project .venv and uv environments are intentionally not scanned."
            )
        elif provider_key == "pipx":
            detail = "pipx scans isolated current-user Python CLI apps and updates them in place."
        elif provider_key == "uv-tool":
            detail = (
                "uv tool scans isolated current-user Python tools managed by uv; "
                "project uv environments are intentionally not scanned."
            )
        elif provider_key == "npm":
            detail = (
                "npm scans globally installed Node packages for the current account. "
                "Use it when you intentionally maintain global Node developer tools."
            )
        elif provider_key == "bun":
            detail = (
                "Bun scans current-user global Bun packages only when Bun has created "
                "a global package manifest. Project dependencies are intentionally not scanned."
            )
        elif provider_key == "cargo":
            detail = (
                "Cargo scans installed Rust crates through cargo-install-update. "
                "Install that cargo subcommand if Cargo is present but this provider is not."
            )
        elif provider_key == "rustup":
            detail = "rustup scans and updates current-user Rust toolchains."
        elif provider_key == "vcpkg":
            detail = (
                "vcpkg classic-mode scans are off by default because upgrades can rebuild "
                "C/C++ dependency trees. Manifest-mode project dependencies are not scanned."
            )
        elif provider_key == "dotnet-tool":
            detail = ".NET Tool scans current-user global .NET CLI tools from NuGet."
        elif provider_key == "powershell":
            detail = "PowerShell 7.x scans CurrentUser PSResourceGet resources."
        elif provider_key == "powershell5":
            detail = (
                "Windows PowerShell 5.x scans CurrentUser PowerShellGet modules only; "
                "AllUsers modules are intentionally skipped; only CurrentUser modules are managed."
            )
        else:
            detail = f"Enable or disable scanning for {label} packages."
        return f"{detail} {availability}"

    def _fallback_icon(self, item: UpdateItem, size: int | None = None) -> Any:
        """Share generated illustrations without ever claiming real artwork is ready."""
        size = size or max(12, self.visuals.px(PACKAGE_ICON_SIZE_DIP))
        style = fallback_vector_style(item)
        cache_key = (style, size, self.palette["mode"])
        if cache_key in self._provider_icon_images:
            return self._provider_icon_images[cache_key]
        try:
            image = self.tk.PhotoImage(data=cached_vector_bitmap(style, size).png)
        except (OSError, ValueError, self.tk.TclError):
            # A native drawing failure must not prevent the inventory from opening.
            image = self.tk.PhotoImage(width=size, height=size)
        self._provider_icon_images[cache_key] = image
        return image

    def _presentation_icon(self, item: UpdateItem, image: Any, size: int | None = None) -> Any:
        """Keep selected vector replacements ahead of even an already-warm raster."""
        if image is not None:
            self._discard_wrench_gallery(item.key)
        return self._fallback_icon(item, size) if preferred_vector_style(item) else image

    def _package_icon_cache_path(
        self,
        item: UpdateItem,
        source: Path,
        size: int,
        *,
        palette_mode: str | None = None,
    ) -> Path:
        return package_icon_cache_path_for_fields(
            item.provider,
            item.package_id,
            item.name,
            source,
            size,
            palette_mode or self.palette["mode"],
        )

    def _details_icon_cache_path(self, item: UpdateItem, source: Path, size: int) -> Path:
        return details_icon_cache_path_for_fields(
            item.provider,
            item.package_id,
            item.name,
            source,
            size,
        )

    def _icon_source_target_size(self) -> int:
        """Largest icon presentation this window needs at its current DPI."""

        return self._icon_source_target_px

    def _item_icon_source_path(self, item: UpdateItem) -> Path | None:
        missing = object()
        cached = self._item_icon_source_cache.get(item.key, missing)
        if cached is not missing:
            return cached
        return resolve_item_icon_source_path(item, self._icon_source_target_size())

    def _known_item_icon_source_path(self, item: UpdateItem) -> Path | None:
        return self._item_icon_source_cache.get(item.key)

    def _display_icon_cache_path(self, raw_path: Path, size: int) -> Path:
        return display_icon_cache_path_for_file(raw_path, size)

    def _start_icon_catalog_load(self) -> None:
        """Load the small accelerator catalog in parallel with initial UI startup."""

        self._icon_catalog_load_generation += 1
        generation = self._icon_catalog_load_generation
        vector_generation = self._icon_prepare_generation
        mode = self.palette["mode"]
        vector_styles = {fallback_vector_style(item) for item in self.items.values()} | {"wrench"}
        vector_sizes = (max(12, self.visuals.px(PACKAGE_ICON_SIZE_DIP)),
                        max(48, self.visuals.px(DETAIL_ICON_SIZE_DIP)))

        def worker() -> None:
            started = time.perf_counter()
            try:
                entries, blobs, error = load_icon_catalog_and_blobs(
                    mode, (*vector_sizes, compact_gallery_size(vector_sizes[1])))
            except Exception as exc:
                # Every load must publish completion, including unexpected I/O
                # failures, so catalog writes and date inference can resume.
                entries, blobs, error = {}, {}, f"{type(exc).__name__}: {exc}"
            self.events.put(
                (
                    "icon_catalog_loaded",
                    (generation, entries, blobs, error, time.perf_counter() - started),
                )
            )
            self._cache_vector_bitmaps(vector_styles, vector_sizes, vector_generation, lazy=True)

        threading.Thread(target=worker, name="wdp-icon-catalog-load", daemon=True).start()

    def _cache_vector_bitmaps(
        self, styles: Iterable[str], sizes: Sequence[int], generation: int, *, lazy: bool = False
    ) -> None:
        """Worker-only: optional warming yields to scans/updates, explicit Lineup requests do not."""
        ordered_styles = sorted(set(styles))
        for size in sorted(set(sizes)):
            for style in ordered_styles:
                while lazy and self.busy:
                    if self._closing or generation != self._icon_prepare_generation:
                        return
                    # Never hold the cache lock or call Tk while waiting for urgent work.
                    time.sleep(0.25)
                with self._icon_catalog_write_lock:
                    if self._closing or generation != self._icon_prepare_generation:
                        return
                    try:
                        bitmap = cached_vector_bitmap(style, size)
                        bitmap.persist()
                        # Existing workers supply bytes for bounded visible or idle
                        # decoding of requested Details-size styles on Tk.
                        if lazy and size == max(sizes, default=0):
                            self.events.put(("vector_icon_resident", (generation, style, size, str(bitmap.path), bitmap.png)))
                    except (OSError, ValueError) as exc:
                        self.logger.event("vector_icon_cache_unavailable", error=str(exc))
                        return  # Bitmap rendering remains available without writable storage.

    def _finish_icon_catalog_load(
        self,
        generation: int,
        entries: dict[str, dict[str, Any]],
        blobs: dict[str, bytes],
        error: str,
        duration: float,
    ) -> None:
        if generation != self._icon_catalog_load_generation or self._closing:
            return
        if self._native_window_interaction_active():
            self.root.after(
                WINDOW_DRAG_BUSY_ANIMATION_POLL_MS,
                self._finish_icon_catalog_load,
                generation,
                entries,
                blobs,
                error,
                duration,
            )
            return
        self._icon_catalog_loaded = True
        self._icon_catalog_entries = entries
        self._icon_catalog_blobs = blobs
        self._icon_catalog_valid_paths = {
            str(icon_cache_dir() / str(record["display"]))
            for entry in entries.values()
            for field in ("list", "compact", "details")
            if isinstance((record := entry.get(field)), dict) and record.get("display")
        }
        self._icon_catalog_list_display_paths = icon_catalog_list_display_paths(
            entries,
            self._icon_catalog_valid_paths,
        )
        current_size = max(12, self.visuals.px(PACKAGE_ICON_SIZE_DIP))
        current_mode = self.palette["mode"]
        self._icon_catalog_decode_queue.clear()
        self._catalog_decode_priority = None
        self._icon_warm_fill_started = time.perf_counter()
        self._icon_warm_fill_counts = {"list": 0, "compact": 0}
        self._icon_warm_fill_reported = set()
        for field, size in (("list", current_size),
                            ("compact", compact_gallery_size(max(48, self.visuals.px(DETAIL_ICON_SIZE_DIP))))):
            for item_key, entry in entries.items():
                record = entry.get(field)
                if not isinstance(record, dict) or record.get("size") != size:
                    continue
                display_path = str(icon_cache_dir() / record.get("display", ""))
                if display_path not in self._icon_catalog_blobs:
                    continue
                if field == "list":
                    memory_key = (item_key, current_size, current_mode)
                    self._package_icon_ready.add(memory_key)
                    self._package_icon_misses.discard(memory_key)
                self._icon_catalog_decode_queue.append((item_key, size, display_path))
        if self.items:
            matched = self._apply_icon_catalog_to_items(tuple(self.items.values()))
            ready = [
                key
                for key in self._package_icon_ready
                if key[0] in matched and key[1] == current_size and key[2] == current_mode
            ]
            self._schedule_ready_icon_memory_load(ready)
            catalog_complete = len(matched) == len(self.items) and all(
                (item_key, current_size, current_mode) in self._package_icon_images
                or (item_key, current_size, current_mode) in self._package_icon_ready
                or (item_key, current_size, current_mode) in self._package_icon_misses
                for item_key in self.items
            )
            if catalog_complete and not self._busy_kind.startswith("scan"):
                # Supersede a slower legacy index subprocess if the catalog
                # arrived after a very fast package scan.
                self._warm_icon_restore_generation += 1
                self._schedule_background_icon_sweep(restart=True, delay_ms=0)
        if self._icon_catalog_decode_queue and self._icon_catalog_decode_after_id is None:
            self._icon_catalog_decode_after_id = self.root.after(0, self._decode_catalog_icons)
        if getattr(self, "_package_gallery_mode", False):
            # A catalog arriving after placeholders were painted supplies new
            # resident PNGs even when row order and artwork identity did not change.
            self._package_gallery_signature = None
            self._schedule_package_gallery_render(prime_resident=True)
        self.logger.event(
            "icon_catalog_loaded",
            entries=len(entries),
            blobs=len(blobs),
            bytes=sum(map(len, blobs.values())),
            duration_seconds=round(duration, 4),
            error=error,
        )
        if self._icon_catalog_write_pending:
            self._schedule_icon_catalog_write()

        self._enqueue_gallery_idle_promotions()

    def _queue_resident_compact_icons(self) -> None:
        """Rewarm the pinned tier after a palette change, using existing worker bytes."""
        size = compact_gallery_size(max(48, self.visuals.px(DETAIL_ICON_SIZE_DIP)))
        pending = set(self._icon_catalog_decode_queue)
        self._catalog_decode_priority = None
        for key, entry in self._icon_catalog_entries.items():
            record = entry.get("compact")
            if not isinstance(record, dict) or record.get("size") != size:
                continue
            path = str(icon_cache_dir() / record["display"])
            queued = (key, size, path)
            if path in self._icon_catalog_blobs and queued not in pending:
                self._icon_catalog_decode_queue.append(queued)
        if self._icon_catalog_decode_queue and self._icon_catalog_decode_after_id is None:
            self._icon_catalog_decode_after_id = self.root.after(1, self._decode_catalog_icons)

    def _prioritize_visible_catalog_decode(self) -> None:
        """Prioritize the visible presentation without adding work to drag callbacks."""
        pending = self._icon_catalog_decode_queue
        if not pending:
            return
        gallery = getattr(self, "_package_gallery_mode", False)
        visible = (frozenset(self._package_gallery_viewport_keys) if gallery
                   else frozenset(self._visible_tree_item_keys()))
        size = (compact_gallery_size(max(48, self.visuals.px(DETAIL_ICON_SIZE_DIP))) if gallery
                else max(12, self.visuals.px(PACKAGE_ICON_SIZE_DIP)))
        signature = (visible, size)
        if signature == getattr(self, "_catalog_decode_priority", None):
            return
        self._catalog_decode_priority = signature
        bands = (deque(), deque(), deque(), deque())
        for record in pending:
            band = (0 if record[0] in visible else 2) + (record[1] != size)
            bands[band].append(record)
        self._icon_catalog_decode_queue = deque(itertools.chain.from_iterable(bands))

    def _icon_slice_limit(self, channel: str) -> int:
        cost = getattr(self, "_icon_decode_cost_ewma", {}).get(channel, .0004)
        return max(8, min(4096, int(ICON_SLICE_BUDGET_SECONDS / max(cost, .00001))))

    def _note_icon_slice(self, elapsed: float, processed: int, channel: str) -> None:
        if processed:
            sample = elapsed / processed
            costs = self.__dict__.setdefault("_icon_decode_cost_ewma", {})
            costs[channel] = .8 * costs.get(channel, sample) + .2 * sample

    def _decode_catalog_icons(self) -> None:
        """Warm pinned list/compact tiers, yielding to Tk redraw between slices."""
        self._icon_catalog_decode_after_id = None
        if self._closing:
            return
        if self._native_window_interaction_active() or getattr(self, "_cache_clear_inflight", False):
            self._icon_catalog_decode_after_id = self.root.after(
                WINDOW_DRAG_BUSY_ANIMATION_POLL_MS, self._decode_catalog_icons)
            return
        started, processed = time.perf_counter(), 0
        self._prioritize_visible_catalog_decode()
        list_size = max(12, self.visuals.px(PACKAGE_ICON_SIZE_DIP))
        compact_size = compact_gallery_size(max(48, self.visuals.px(DETAIL_ICON_SIZE_DIP)))
        mode = self.palette["mode"]
        self._package_gallery_scaled_context = (self._icon_prepare_generation,
            max(48, self.visuals.px(DETAIL_ICON_SIZE_DIP)), mode)
        limit = self._icon_slice_limit("catalog")
        moving = (getattr(self, "_package_gallery_drag", None)
                  or getattr(self, "_package_gallery_motion_after_id", None))
        budget = .001 if moving else ICON_SLICE_BUDGET_SECONDS
        while self._icon_catalog_decode_queue:
            item_key, size, path = self._icon_catalog_decode_queue.popleft()
            if size not in (list_size, compact_size):
                continue
            item = self.items.get(item_key)
            entry = self._icon_catalog_entries.get(item_key, {})
            if item is not None and (entry.get("identity") != list(item_icon_identity(item))
                                     or entry.get("version") != item.current):
                continue
            field = "list" if size == list_size else "compact"
            if field == "compact":
                identity = entry.get("identity", ["", "", "", "", ""])
                artwork_item = item or UpdateItem(provider=identity[0], package_id=identity[1],
                                                  name=identity[2], current="", available="")
                if preferred_vector_style(artwork_item):
                    continue  # Preserve the same vector precedence as the normal presentation.
            memory_key = (item_key, size, mode)
            cache = self._package_icon_images if field == "list" else self._compact_icon_images
            if memory_key not in cache and path in self._icon_catalog_blobs:
                image = self._load_catalog_icon_image(path)
                if image is not None:
                    cache[memory_key] = image
                    if field == "compact":
                        self._compact_icon_tokens[memory_key] = self._package_gallery_icon_token(item_key)
                    elif item_key in self.items and self.tree.exists(item_key):
                        getattr(self, "_tree_row_presentations", {}).pop(item_key, None)
                        self.tree.item(item_key, image=self._presentation_icon(self.items[item_key], image, size), text="")
                        self._tree_icon_kind[item_key] = "app"
            processed += 1
            counts = getattr(self, "_icon_warm_fill_counts", {})
            counts[field] = counts.get(field, 0) + 1
            if processed >= limit or time.perf_counter() - started >= budget:
                break
        self._note_icon_slice(time.perf_counter() - started, processed, "catalog")
        if getattr(self, "_package_gallery_mode", False):
            self._publish_resident_gallery_icons()
        if self._icon_catalog_decode_queue:
            # A positive continuation lets idle redraw run; never chain after(0).
            self._icon_catalog_decode_after_id = self.root.after(1, self._decode_catalog_icons)
        elif processed and self._icon_sort_active:
            self._schedule_icon_sort_refresh()
        pending_sizes = {record[1] for record in self._icon_catalog_decode_queue}
        reported = getattr(self, "_icon_warm_fill_reported", None)
        if reported is None:
            self._icon_warm_fill_reported = reported = set()
        for field, size in (("list", list_size), ("compact", compact_size)):
            if size not in pending_sizes and field not in reported:
                reported.add(field)
                self.logger.event("icon_warm_fill", tier=field,
                    count=getattr(self, "_icon_warm_fill_counts", {}).get(field, 0),
                    seconds=round(time.perf_counter() - getattr(self, "_icon_warm_fill_started", started), 4))

    def _apply_icon_catalog_to_items(self, items: Sequence[UpdateItem]) -> set[str]:
        """Reuse only catalog state whose full package identity still matches."""

        matched: set[str] = set()
        size = max(12, self.visuals.px(PACKAGE_ICON_SIZE_DIP))
        mode = self.palette["mode"]
        for item in items:
            entry = self._icon_catalog_entries.get(item.key)
            if not isinstance(entry, dict) or entry.get("identity") != list(
                item_icon_identity(item)
            ) or (entry.get("version") and entry["version"] != item.current):
                continue
            source_text = str(entry.get("source") or "")
            source = Path(source_text) if source_text else None
            self._item_icon_source_cache[item.key] = source
            matched.add(item.key)
            memory_key = (item.key, size, mode)
            record = entry.get("list")
            display_path = ""
            if isinstance(record, dict) and record.get("size") == size:
                display_path = str(icon_cache_dir() / str(record.get("display", "")))
            if display_path and display_path in self._icon_catalog_valid_paths:
                self._package_icon_ready.add(memory_key)
                self._package_icon_misses.discard(memory_key)
            elif source is None or icon_catalog_miss_is_current(entry, "list"):
                self._package_icon_ready.discard(memory_key)
                self._package_icon_misses.add(memory_key)
        return matched

    def _schedule_icon_catalog_write(self) -> None:
        """Coalesce completion checkpoints, with at most one writer in flight."""

        if self._closing or self._cache_clear_inflight or not self.items:
            return
        self._icon_catalog_write_pending = True
        if (
            not self._icon_catalog_loaded
            or self._icon_catalog_write_active
            or self._icon_catalog_write_after_id is not None
        ):
            return
        self._icon_catalog_write_after_id = self.root.after(100, self._start_icon_catalog_write)

    def _invalidate_item_icon_caches(self, keys: set[str]) -> None:
        """Drop only changed installations; existing source-versioned PNGs stay on disk."""

        if not keys:
            return
        self._icon_catalog_write_generation += 1
        self._icon_catalog_write_active = False
        self._warm_icon_restore_generation += 1
        revisions = getattr(self, "_icon_item_revisions", {})
        self._icon_item_revisions = revisions
        for key in keys:
            revisions[key] = revisions.get(key, 0) + 1
            for pending in tuple(self._icon_prepare_inflight):
                if pending[0] == key or pending[0].endswith(":" + key):
                    self._icon_prepare_inflight.discard(pending)
                    self._details_icon_callbacks.pop(pending, None)
            self._icon_catalog_entries.pop(key, None)
            self._item_icon_source_cache.pop(key, None)
            self._discard_icon_gallery_preparation(key)
            self._icon_gallery_queued_jobs.pop(key, None)
            for callback in self._icon_gallery_inflight.pop(key, ()):
                with contextlib.suppress(self.tk.TclError):
                    callback(IconGalleryMemoryBundle(b"", 0), "Artwork changed; reopen Icon Lineup.")
        for cache in (self._package_icon_images, self._details_icon_images, getattr(self, "_compact_icon_images", {}), getattr(self, "_compact_icon_tokens", {})):
            for memory_key in list(cache):
                if memory_key[0] in keys:
                    del cache[memory_key]
        evidence_cache = getattr(self, "_details_icon_evidence_cache", {})
        for cache_key in tuple(evidence_cache):
            if cache_key[0] in keys:
                del evidence_cache[cache_key]
        self._package_icon_ready.difference_update(key for key in tuple(self._package_icon_ready) if key[0] in keys)
        self._package_icon_misses.difference_update(key for key in tuple(self._package_icon_misses) if key[0] in keys)
        self._icon_catalog_decode_queue = deque(
            record for record in self._icon_catalog_decode_queue if record[0] not in keys
        )
        self._details_background_completed_signature = ""
        self._icon_catalog_list_display_paths = icon_catalog_list_display_paths(
            self._icon_catalog_entries, self._icon_catalog_valid_paths,
        )
        self.logger.event("icon_sources_invalidated", item_count=len(keys))
        self._schedule_package_gallery_render()

    def _start_icon_catalog_write(self) -> None:
        """Capture the latest state on Tk; build and atomically save off-thread."""

        self._icon_catalog_write_after_id = None
        self._icon_catalog_write_pending = False
        if self._closing or self._cache_clear_inflight or not self.items:
            return
        self._icon_catalog_write_generation += 1
        generation = self._icon_catalog_write_generation
        self._icon_catalog_write_active = True
        items = tuple(dataclasses.replace(item) for item in self.items.values())
        sources = dict(self._item_icon_source_cache)
        existing = {key: dict(value) for key, value in self._icon_catalog_entries.items()}
        list_size = max(12, self.visuals.px(PACKAGE_ICON_SIZE_DIP))
        details_size = max(48, self.visuals.px(DETAIL_ICON_SIZE_DIP))
        mode = self.palette["mode"]
        resident_paths = set(self._icon_catalog_blobs)
        full_inventory = (
            self._last_scan_all_packages and self._scan_results_current and not self._scan_active
        )

        def worker() -> None:
            started = time.perf_counter()
            new_blobs: dict[str, bytes] = {}
            try:
                entries = build_icon_catalog_entries(
                    items,
                    sources,
                    list_size,
                    details_size,
                    existing,
                    full_inventory=full_inventory,
                )
                if generation != self._icon_catalog_write_generation:
                    return
                with self._icon_catalog_write_lock:
                    if generation != self._icon_catalog_write_generation:
                        return
                    write_icon_catalog(entries)
                    try:
                        write_icon_packs(entries, mode)
                    except (OSError, ValueError) as exc:
                        self.logger.event("icon_pack_write_failed", error=str(exc))
                for entry in entries.values():
                    for field in ("details", "compact"):
                        record = entry.get(field)
                        if not isinstance(record, dict):
                            continue
                        path = icon_cache_dir() / record["display"]
                        if str(path) in resident_paths or str(path) in new_blobs:
                            continue
                        try:
                            if path.stat().st_size > ICON_CATALOG_SINGLE_BLOB_MAX_BYTES:
                                continue
                            data = path.read_bytes()
                            info = path.stat()
                            if ([info.st_mtime_ns, info.st_size] == record["display_stat"]
                                    and _icon_png_integrity(data)):
                                new_blobs[str(path)] = data
                        except OSError:
                            continue
                error = ""
            except (OSError, TypeError, ValueError) as exc:
                entries = {}
                error = f"{type(exc).__name__}: {exc}"
            self.events.put(
                (
                    "icon_catalog_written",
                    (
                        generation,
                        entries,
                        error,
                        time.perf_counter() - started,
                        new_blobs,
                    ),
                )
            )

        threading.Thread(target=worker, name="wdp-icon-catalog-write", daemon=True).start()

    def _finish_icon_catalog_write(
        self,
        generation: int,
        entries: dict[str, dict[str, Any]],
        error: str,
        duration: float,
        blobs: Mapping[str, bytes] | None = None,
    ) -> None:
        if generation != self._icon_catalog_write_generation or self._closing:
            return
        self._icon_catalog_write_active = False
        if not error:
            # A catalog writer may have snapshotted just before a Details worker
            # published its record. Keep that newer resident record when the
            # source and package identity still agree.
            for key, entry in entries.items():
                previous = self._icon_catalog_entries.get(key, {})
                if ("details" not in entry and "details" in previous
                        and all(entry.get(field) == previous.get(field)
                                for field in ("identity", "version", "source", "source_stat"))):
                    path = str(icon_cache_dir() / previous["details"]["display"])
                    if path in self._icon_catalog_blobs and path in self._icon_catalog_valid_paths:
                        entry["details"] = previous["details"]
                        if "compact" in previous:
                            entry["compact"] = previous["compact"]
            self._icon_catalog_entries = entries
            self._icon_catalog_valid_paths.update(
                str(icon_cache_dir() / str(record["display"]))
                for entry in entries.values()
                for field in ("list", "compact", "details")
                if isinstance((record := entry.get(field)), dict) and record.get("display")
            )
            self._icon_catalog_list_display_paths = icon_catalog_list_display_paths(
                entries,
                self._icon_catalog_valid_paths,
            )
        if not error and blobs:
            for key, entry in entries.items():
                item = self.items.get(key)
                if item is not None and entry.get("source"):
                    self._publish_resident_details_icon(item, Path(entry["source"]), entry, blobs)
        self.logger.event(
            "icon_catalog_written",
            entries=len(entries),
            list_icons=sum(isinstance(entry.get("list"), dict) for entry in entries.values()),
            details_icons=sum(isinstance(entry.get("details"), dict) for entry in entries.values()),
            duration_seconds=round(duration, 4),
            error=error,
        )
        if self._icon_catalog_write_pending:
            self._schedule_icon_catalog_write()

        self._enqueue_gallery_idle_promotions()

    def _load_cached_icon_image(self, path: Path, size: int) -> Any | None:
        if not path.exists():
            return None
        display_path = self._display_icon_cache_path(path, size)
        if not display_path.exists():
            return None
        load_path = display_path

        def drop_bad_cache() -> None:
            with contextlib.suppress(OSError):
                if path.name.startswith(("appicon-", "detailsicon-", "displayicon-")):
                    path.unlink()
                if load_path != path and load_path.name.startswith("displayicon-"):
                    load_path.unlink()

        # Rows-based check first: no Tcl churn, and blank icons never allocate
        # a PhotoImage. Undecodable-here variants fall back to the Tk check.
        load_key = str(load_path)
        catalog_validated = load_key in self._icon_catalog_valid_paths
        detail = True if catalog_validated else icon_png_has_visual_detail(load_path)
        if detail is False:
            drop_bad_cache()
            return None
        try:
            data = self._icon_catalog_blobs.get(load_key)
            image = (
                self.tk.PhotoImage(data=data, format="png")
                if data is not None
                else self.tk.PhotoImage(file=load_key, format="png")
            )
        except Exception:
            self._icon_catalog_blobs.pop(load_key, None)
            self._icon_catalog_valid_paths.discard(load_key)
            drop_bad_cache()
            return None
        if detail is None and not tk_image_has_visual_detail(image):
            drop_bad_cache()
            return None
        try:
            width = max(1, int(image.width()))
            height = max(1, int(image.height()))
        except Exception:
            return image
        factor = max(1, math.ceil(max(width, height) / max(1, size)))
        if factor > 1:
            with contextlib.suppress(Exception):
                image = image.subsample(factor, factor)
        return image

    def _load_catalog_icon_image(self, display_path: str) -> Any | None:
        """Decode one path already validated by the off-thread catalog loader."""

        if display_path not in self._icon_catalog_valid_paths:
            return None
        try:
            data = self._icon_catalog_blobs.get(display_path)
            image = (
                self.tk.PhotoImage(data=data, format="png")
                if data is not None
                else self.tk.PhotoImage(file=display_path, format="png")
            )
            if data is not None:
                # Cached photos are immutable. Share their exact input bytes for
                # compact conversion; Tk subsample/zoom copies do not inherit this.
                image._windevpilot_source_png = data
            return image
        except Exception:
            self._icon_catalog_blobs.pop(display_path, None)
            self._icon_catalog_valid_paths.discard(display_path)
            for key, path_text in tuple(self._icon_catalog_list_display_paths.items()):
                if path_text == display_path:
                    self._icon_catalog_list_display_paths.pop(key, None)
            return None

    def _resident_details_icon_path(self, item: UpdateItem, size: int) -> str | None:
        """Share the identity/size/validation gate for idle planning and decoding."""
        entry = getattr(self, "_icon_catalog_entries", {}).get(item.key)
        if (isinstance(entry, dict) and entry.get("identity") == list(item_icon_identity(item))
                and entry.get("version") == item.current):
            record = entry.get("details")
            if isinstance(record, dict) and record.get("size") == size:
                path = str(icon_cache_dir() / str(record.get("display", "")))
                if (path in self._icon_catalog_blobs and path in self._icon_catalog_valid_paths):
                    return path
        return None

    def _details_icon_image_if_ready(
        self, item: UpdateItem, size: int, *, resident_only: bool = False,
    ) -> Any | None:
        """Optionally restrict promotion to decoded art or validated resident PNGs."""
        if style := preferred_vector_style(item):
            if resident_only:
                return self._provider_icon_images.get((style, size, self.palette["mode"]))
            return self._fallback_icon(item, size)
        memory_key = (item.key, size, self.palette["mode"])
        memory_image = self._details_icon_images.get(memory_key)
        if memory_image is not None:
            self._details_icon_images.move_to_end(memory_key)
            return memory_image
        # The catalog was validated off-thread. Promote resident PNG bytes before
        # deriving paths or consulting source/raw-file metadata on the GUI thread.
        if path := self._resident_details_icon_path(item, size):
            image = self._load_catalog_icon_image(path)
            if image is not None:
                dims = self._icon_catalog_entries[item.key]["details"].get("dims", (size, size))
                factor = max(1, math.ceil(max(dims) / max(1, size)))
                if factor > 1:
                    image = image.subsample(factor, factor)
                self._remember_details_icon(memory_key, image)
                return image
        if resident_only:
            return None
        source = self._known_item_icon_source_path(item)
        if source is None:
            return None
        cache_path = self._details_icon_cache_path(item, source, size)
        display_path = self._display_icon_cache_path(cache_path, size)
        if not display_path.exists():
            return None
        image = self._load_cached_icon_image(cache_path, size)
        if image is None:
            return None
        self._remember_details_icon(memory_key, image)
        return image

    def _remember_details_icon(self, memory_key: tuple[str, int, str], image: Any) -> None:
        """Bound reusable decoded artwork, accounting for each entry's own DPI size.

        The charge estimates pixel storage plus overhead; it is not process RSS.
        Visible widgets retain their own references after an LRU eviction.
        """
        cache = self._details_icon_images
        cache[memory_key] = image
        self._discard_wrench_gallery(memory_key[0])

    def _details_evidence_key(self, item: UpdateItem, size: int, source: Path) -> tuple[Any, ...]:
        return (item.key, size, item_icon_identity(item), item.current, str(source),
                getattr(self, "_icon_item_revisions", {}).get(item.key, 0))

    def _remember_details_icon_evidence(
        self, item: UpdateItem, size: int, source: Path, evidence: Mapping[str, Any] | None,
    ) -> None:
        if evidence is None:
            return  # Missing metadata stays retryable on later Details navigation.
        cache = getattr(self, "_details_icon_evidence_cache", None)
        if cache is None:
            cache = self._details_icon_evidence_cache = OrderedDict()
        key = self._details_evidence_key(item, size, source)
        cache[key] = dict(evidence)
        cache.move_to_end(key)
        while len(cache) > DETAIL_ICON_MEMORY_LIMIT:
            cache.popitem(last=False)

    def _details_icon_evidence(
        self, item: UpdateItem, size: int, *, generated_fallback: bool = False,
    ) -> dict[str, Any] | None:
        """RAM-only provenance lookup; workers refine missing raster metadata."""
        source = (None if generated_fallback or preferred_vector_style(item)
                  else self._known_item_icon_source_path(item))
        if source is None:
            style = fallback_vector_style(item)
            return {"generated_vector": style, "generated_png": str(vector_bitmap_cache_path(style, size)),
                    "metadata_ready": True}
        cache = getattr(self, "_details_icon_evidence_cache", {})
        key = self._details_evidence_key(item, size, source)
        evidence = cache.get(key)
        if evidence is not None:
            cache.move_to_end(key)
            return dict(evidence)
        return None

    def _details_icon_placeholder(self, item: UpdateItem, size: int) -> tuple[Any, bool]:
        """Return the immediate image and whether it uses the generated fallback."""
        if preferred_vector_style(item):
            return self._fallback_icon(item, size), True
        list_size = max(12, self.visuals.px(PACKAGE_ICON_SIZE_DIP))
        small = self._package_icon_images.get((item.key, list_size, self.palette["mode"]))
        if small is not None:
            with contextlib.suppress(Exception):
                largest = max(1, int(small.width()), int(small.height()))
                zoom = max(1, size // largest)
                return (small.zoom(zoom, zoom) if zoom > 1 else small), False
        return self._fallback_icon(item, size), True

    def _prepare_details_icon_cache_file(
        self,
        item: UpdateItem,
        size: int,
        generation: int,
        coalesce_key: str,
        *,
        priority: int = 0,
    ) -> tuple[bool, Path | None]:
        source = self._item_icon_source_path(item)
        if source is None:
            return False, None
        cache_path = self._details_icon_cache_path(item, source, size)
        ok, _upscaled, reason = self.icon_renderer.prepare(
            source,
            cache_path,
            small_shell_icon=False,
            target_size=size,
            fit_art_at_scale=2.0,
            generation=generation,
            priority=priority,
            coalesce_key=coalesce_key,
        )
        miss_path = icon_render_miss_path(cache_path, size)
        if ok:
            with contextlib.suppress(OSError):
                miss_path.unlink()
        elif reason in {
            "no usable icon could be extracted",
            "icon format could not be normalized or rendered",
        }:
            with contextlib.suppress(OSError):
                write_icon_render_miss(
                    cache_path,
                    size,
                    reason or "no usable large icon could be prepared",
                )
        return ok, source

    def _queue_details_icon_prepare(
        self,
        item: UpdateItem,
        size: int,
        callback: Callable[[str], None],
        *,
        coalesce_key: str,
    ) -> None:
        memory_key = (
            f"details:{coalesce_key}:{item.key}",
            size,
            self.palette["mode"],
        )
        if memory_key in self._icon_prepare_inflight:
            self._details_icon_callbacks.setdefault(memory_key, []).append(callback)
            return
        self._details_icon_callbacks[memory_key] = [callback]
        self._icon_prepare_inflight.add(memory_key)
        generation = self._icon_prepare_generation
        list_size = max(12, self.visuals.px(PACKAGE_ICON_SIZE_DIP))
        revision = getattr(self, "_icon_item_revisions", {}).get(item.key, 0)

        def worker(
            snapshot: UpdateItem, snapshot_key: tuple[str, int, str], snapshot_generation: int
        ) -> None:
            ok = False
            source: Path | None = None
            unavailable_until = 0.0
            evidence_result = None
            resident_entries, resident_blobs = {}, {}
            try:
                ok, source = self._prepare_details_icon_cache_file(
                    snapshot, size, snapshot_generation, coalesce_key
                )
                if ok and source is not None:
                    if coalesce_key.startswith("package-gallery:"):
                        resident_entries, resident_blobs = prepared_details_icon_payload(
                            (snapshot,), source, list_size, size)
                    else:
                        raw_path = self._details_icon_cache_path(snapshot, source, size)
                        evidence_result = (item_icon_identity(snapshot), snapshot.current,
                                           prepared_icon_evidence(source, raw_path, self._display_icon_cache_path(raw_path, size)))
                if not ok and coalesce_key.startswith("package-gallery:"):
                    # Only a completed source search or a current render-miss
                    # record establishes missing artwork; exceptions stay unknown.
                    unavailable_until = (
                        time.time() + ICON_CATALOG_NEGATIVE_SOURCE_TTL_SECONDS if source is None
                        else icon_render_miss_expires_at(self._details_icon_cache_path(snapshot, source, size), size)
                    )
            except Exception:
                ok = False
            self.events.put(
                (
                    "details_icon_prepared",
                    (snapshot.key, size, snapshot_key, ok, source, snapshot_generation, revision, unavailable_until, evidence_result, resident_entries, resident_blobs),
                )
            )

        threading.Thread(target=worker, args=(dataclasses.replace(item), memory_key, generation), daemon=True).start()

    def _finish_details_icon_prepare(
        self,
        item_key: str,
        size: int,
        memory_key: tuple[str, int, str],
        ok: bool,
        source: Path | None,
        generation: int,
        revision: int = 0,
        unavailable_until: float = 0.0,
        evidence_result: tuple[tuple[str, ...], str, dict[str, Any] | None] | None = None,
        resident_entries: Mapping[str, Mapping[str, Any]] | None = None,
        resident_blobs: Mapping[str, bytes] | None = None,
    ) -> None:
        if (generation != self._icon_prepare_generation
                or revision != getattr(self, "_icon_item_revisions", {}).get(item_key, 0)):
            return
        self._icon_prepare_inflight.discard(memory_key)
        callbacks = self._details_icon_callbacks.pop(memory_key, [])
        if self._closing:
            return
        if memory_key[0].startswith("details:package-gallery:"):
            if not ok and unavailable_until > time.time():
                token = (generation, size, memory_key[2], revision)
                self._package_gallery_misses[item_key] = (token, unavailable_until)
                if item_key in self._package_gallery_slots:
                    self._package_gallery_signature = None
                    self._schedule_package_gallery_render()
            elif ok:
                self._package_gallery_misses.pop(item_key, None)
        if not ok:
            return
        self._item_icon_source_cache[item_key] = source
        item = self.items.get(item_key)
        if (item is not None and source is not None and evidence_result is not None
                and evidence_result[:2] == (item_icon_identity(item), item.current)):
            self._remember_details_icon_evidence(item, size, source, evidence_result[2])
        if item is not None and resident_entries:
            self._publish_resident_details_icon(
                item, source, resident_entries.get(item_key), resident_blobs or {})
        for callback in callbacks:
            callback(item_key)

    @staticmethod
    def _background_icon_failure_event(
        source: Path | None,
        failure_reason: str,
    ) -> tuple[str, str]:
        """Separate an expected provider-marker fallback from a render failure."""

        if source is None and failure_reason == "no local icon source was found":
            return "background_icon_source_unavailable", "provider-marker"
        return "background_icon_prepare_failed", ""

    def _prepare_item_icon_cache_file(
        self, item: UpdateItem, size: int, generation: int
    ) -> tuple[bool, bool, Path | None, str]:
        source = self._item_icon_source_path(item)
        if source is None:
            return False, False, None, "no local icon source was found"
        cache_path = self._package_icon_cache_path(item, source, size)
        ok, upscaled, reason = self.icon_renderer.prepare(
            source,
            cache_path,
            small_shell_icon=True,
            target_size=size,
            fit_art_at_scale=None,
            generation=generation,
            priority=10,
        )
        miss_path = icon_render_miss_path(cache_path, size)
        if ok:
            with contextlib.suppress(OSError):
                miss_path.unlink()
        elif reason in {
            "no usable icon could be extracted",
            "icon format could not be normalized or rendered",
        }:
            with contextlib.suppress(OSError):
                write_icon_render_miss(
                    cache_path,
                    size,
                    reason or "no usable list icon could be prepared",
                )
        return ok, upscaled, source, reason

    def _queue_icon_prepare(self, item: UpdateItem, size: int) -> None:
        memory_key = (item.key, size, self.palette["mode"])
        if (
            memory_key in self._package_icon_images
            or memory_key in self._package_icon_misses
            or memory_key in self._icon_prepare_inflight
        ):
            return
        list_icon_inflight = any(
            not key[0].startswith("details:") for key in self._icon_prepare_inflight
        )
        if list_icon_inflight:
            return
        self._cancel_after_id("_icon_batch_finish_after_id")
        if not self._lazy_icon_batch_active:
            self._lazy_icon_batch_active = True
            self._lazy_icon_batch_cached = 0
            self._lazy_icon_batch_failed = 0
            self._lazy_icon_batch_upscaled = 0
            if not self._lazy_icon_log_announced:
                self._append_log("Icon loading started", show_in_ui=False)
                self._lazy_icon_log_announced = True
        self._icon_prepare_inflight.add(memory_key)
        generation = self._icon_prepare_generation
        revision = getattr(self, "_icon_item_revisions", {}).get(item.key, 0)

        def worker(
            snapshot: UpdateItem, snapshot_key: tuple[str, int, str], snapshot_generation: int
        ) -> None:
            ok = False
            upscaled = False
            source: Path | None = None
            failure_reason = ""
            try:
                ok, upscaled, source, failure_reason = self._prepare_item_icon_cache_file(
                    snapshot, size, snapshot_generation
                )
                if not ok and not failure_reason:
                    failure_reason = "no usable icon could be extracted or rendered"
            except Exception as exc:
                ok = False
                failure_reason = f"{type(exc).__name__}: {exc}"
            self.events.put(
                (
                    "icon_prepared",
                    (
                        snapshot.key,
                        size,
                        snapshot_key,
                        ok,
                        upscaled,
                        source,
                        snapshot_generation,
                        failure_reason,
                        revision,
                    ),
                )
            )

        threading.Thread(target=worker, args=(dataclasses.replace(item), memory_key, generation), daemon=True).start()

    def _finish_icon_prepare(
        self,
        item_key: str,
        size: int,
        memory_key: tuple[str, int, str],
        ok: bool,
        upscaled: bool,
        source: Path | None,
        generation: int,
        failure_reason: str,
        revision: int = 0,
    ) -> None:
        if (generation != self._icon_prepare_generation
                or revision != getattr(self, "_icon_item_revisions", {}).get(item_key, 0)):
            return
        self._icon_prepare_inflight.discard(memory_key)
        self._item_icon_source_cache[item_key] = source
        # PNG files are palette-neutral. Release the original worker key, then
        # publish under the current mode if the theme changed during preparation.
        memory_key = (item_key, size, self.palette["mode"])
        if ok:
            self._lazy_icon_batch_cached += 1
            self._package_icon_misses.discard(memory_key)
            self._package_icon_ready.add(memory_key)
            self._schedule_ready_icon_memory_load((memory_key,))
            if upscaled:
                self._lazy_icon_batch_upscaled += 1
        else:
            self._lazy_icon_batch_failed += 1
            self._package_icon_ready.discard(memory_key)
            item = self.items.get(item_key)
            event_name, fallback = self._background_icon_failure_event(
                source,
                failure_reason,
            )
            self.logger.event(
                event_name,
                item_key=item_key,
                package_id=item.package_id if item is not None else "",
                provider=item.provider if item is not None else "",
                source=str(self._known_item_icon_source_path(item)) if item is not None else "",
                target_size=size,
                reason=failure_reason,
                fallback=fallback,
            )
        if self._closing or not ok:
            if not ok:
                self._package_icon_misses.add(memory_key)
        # Loading a PhotoImage and repainting Treeview rows are UI-thread work.
        # Defer both (including advancement after a miss) until scrolling has
        # settled instead of doing them for every worker completion event.
        if not self._closing:
            self._schedule_visible_icon_hydration(delay_ms=80)
            self._schedule_background_icon_sweep()
            self._finish_background_icon_sweep_if_idle()
        if self._lazy_icon_batch_active:
            self._cancel_after_id("_icon_batch_finish_after_id")
            self._icon_batch_finish_after_id = self.root.after(700, self._finish_lazy_icon_batch)

    def _finish_lazy_icon_batch(self) -> None:
        self._icon_batch_finish_after_id = None
        if self._icon_background_sweep_active:
            self._finish_background_icon_sweep_if_idle()
            return
        list_icon_inflight = any(
            not key[0].startswith("details:") for key in self._icon_prepare_inflight
        )
        if not self._lazy_icon_batch_active or list_icon_inflight:
            return
        self.logger.event(
            "background_icon_batch_finished",
            prepared=self._lazy_icon_batch_cached,
            upscaled=self._lazy_icon_batch_upscaled,
            skipped=self._lazy_icon_batch_failed,
        )
        parts = [f"{self._lazy_icon_batch_cached} app icon(s) prepared"]
        if self._lazy_icon_batch_upscaled:
            parts.append(f"{self._lazy_icon_batch_upscaled} upscaled")
        if self._lazy_icon_batch_failed:
            parts.append(f"{self._lazy_icon_batch_failed} skipped")
        if self._lazy_icon_batch_cached:
            self._append_log(
                "Background icon batch: " + "; ".join(parts) + ".",
                show_in_ui=False,
            )
            if self._icon_sort_active:
                self._schedule_icon_sort_refresh()
        self._lazy_icon_batch_active = False

    def _item_icon_if_ready(self, item: UpdateItem) -> Any | None:
        if preferred_vector_style(item):
            return self._fallback_icon(item)
        size = max(12, self.visuals.px(PACKAGE_ICON_SIZE_DIP))
        memory_key = (item.key, size, self.palette["mode"])
        if memory_key in self._package_icon_images:
            return self._package_icon_images[memory_key]
        if memory_key in self._package_icon_misses:
            return None
        catalog_path = self._icon_catalog_list_display_paths.get((item.key, size), "")
        if catalog_path:
            image = self._load_catalog_icon_image(catalog_path)
            if image is not None:
                self._package_icon_images[memory_key] = image
                self._package_icon_misses.discard(memory_key)
                self._package_icon_ready.add(memory_key)
                return image
        source = self._known_item_icon_source_path(item)
        if source is None:
            return None
        cache_path = self._package_icon_cache_path(item, source, size)
        display_path = self._display_icon_cache_path(cache_path, size)
        if not display_path.exists():
            return None
        image = self._load_cached_icon_image(cache_path, size)
        if image is None:
            self._package_icon_ready.discard(memory_key)
            self._package_icon_misses.add(memory_key)
            return None
        self._package_icon_images[memory_key] = image
        self._package_icon_misses.discard(memory_key)
        self._package_icon_ready.add(memory_key)
        return image

    def _start_warm_icon_cache_restore(self) -> None:
        """Index an existing GUI-size cache without blocking Tk or decoding images."""
        icon_size = max(12, self.visuals.px(PACKAGE_ICON_SIZE_DIP))
        source_target_size = self._icon_source_target_size()
        palette_mode = self.palette["mode"]
        snapshots = tuple(dataclasses.replace(item) for item in self.items.values())
        vector_sizes = (icon_size, max(48, self.visuals.px(DETAIL_ICON_SIZE_DIP)))
        self._warm_icon_restore_generation += 1
        restore_generation = self._warm_icon_restore_generation
        scan_generation = self._active_scan_generation
        prepare_generation = self._icon_prepare_generation

        def worker() -> None:
            cache_root = icon_cache_dir()
            with contextlib.suppress(OSError):
                prune_stale_icon_cache_versions()
            cache_count = 0
            if cache_root.exists():
                for _path in cache_root.glob(f"{DISPLAY_ICON_CACHE_PREFIX}{icon_size}px-*.png"):
                    cache_count += 1
                    if cache_count >= WARM_ICON_CACHE_MIN_COUNT:
                        break
            sources: dict[str, Path | None] = {}
            ready_keys: list[tuple[str, int, str]] = []
            unavailable_keys: list[tuple[str, int, str]] = []
            index_error = ""
            if cache_count >= WARM_ICON_CACHE_MIN_COUNT:
                (
                    sources,
                    ready_item_keys,
                    unavailable_item_keys,
                    index_error,
                ) = warm_icon_cache_index_isolated(
                    snapshots, icon_size, palette_mode, source_target_size
                )
                ready_keys = [(item_key, icon_size, palette_mode) for item_key in ready_item_keys]
                unavailable_keys = [
                    (item_key, icon_size, palette_mode) for item_key in unavailable_item_keys
                ]
            self.events.put(
                (
                    "warm_icon_cache_indexed",
                    (
                        restore_generation,
                        scan_generation,
                        prepare_generation,
                        cache_count,
                        sources,
                        ready_keys,
                        unavailable_keys,
                        index_error,
                    ),
                )
            )
            self._cache_vector_bitmaps(
                (fallback_vector_style(item) for item in snapshots), vector_sizes, prepare_generation, lazy=True
            )

        threading.Thread(target=worker, name="wdp-warm-icon-index", daemon=True).start()

    def _finish_warm_icon_cache_restore(
        self,
        restore_generation: int,
        scan_generation: int,
        prepare_generation: int,
        cache_count: int,
        sources: dict[str, Path | None],
        ready_keys: list[tuple[str, int, str]],
        unavailable_keys: list[tuple[str, int, str]],
        index_error: str,
    ) -> None:
        if (
            restore_generation != self._warm_icon_restore_generation
            or scan_generation != self._active_scan_generation
            or prepare_generation != self._icon_prepare_generation
            or self._closing
        ):
            return
        if self._native_window_interaction_active():
            self.root.after(
                WINDOW_DRAG_BUSY_ANIMATION_POLL_MS,
                self._finish_warm_icon_cache_restore,
                restore_generation,
                scan_generation,
                prepare_generation,
                cache_count,
                sources,
                ready_keys,
                unavailable_keys,
                index_error,
            )
            return
        for item_key, source in sources.items():
            if item_key in self.items:
                self._item_icon_source_cache[item_key] = source
        index_ran = cache_count >= WARM_ICON_CACHE_MIN_COUNT
        if index_ran:
            fresh_ready = set(ready_keys)
            fresh_unavailable = set(unavailable_keys)
            icon_size = max(12, self.visuals.px(PACKAGE_ICON_SIZE_DIP))
            palette_mode = self.palette["mode"]
            self._package_icon_ready = {
                key
                for key in self._package_icon_ready
                if key[1] != icon_size or key[2] != palette_mode
            } | fresh_ready
            self._package_icon_misses = {
                key
                for key in self._package_icon_misses
                if key[1] != icon_size or key[2] != palette_mode
            } | fresh_unavailable
            for memory_key in list(self._package_icon_images):
                item_key, size, mode = memory_key
                if item_key not in self.items or (
                    size == icon_size and mode == palette_mode and memory_key not in fresh_ready
                ):
                    self._package_icon_images.pop(memory_key, None)
        else:
            self._package_icon_ready.update(ready_keys)
            self._package_icon_misses.update(unavailable_keys)
        self.logger.event(
            "warm_icon_cache_indexed",
            cache_threshold=WARM_ICON_CACHE_MIN_COUNT,
            cache_entries_seen=cache_count,
            matched_ready_icons=len(ready_keys),
            matched_unavailable_icons=len(unavailable_keys),
            package_sources_resolved=len(sources),
            error=index_error,
        )
        if ready_keys:
            self._schedule_ready_icon_memory_load(ready_keys)
            if self._icon_sort_active:
                self._schedule_icon_sort_refresh()
            self._schedule_visible_icon_hydration(delay_ms=0, restart=True)
        elif index_ran:
            self._schedule_visible_icon_hydration(delay_ms=0, restart=True)
        if index_ran and sources and not index_error:
            self._schedule_icon_catalog_write()
        self._schedule_background_icon_sweep(restart=True, delay_ms=120)

    def _schedule_ready_icon_memory_load(
        self,
        ready_keys: Sequence[tuple[str, int, str]],
        *,
        delay_ms: int = 0,
    ) -> None:
        """Load ready GUI-size icons into Tk memory independently of scrolling."""

        if self._closing or not hasattr(self, "tree"):
            return
        for memory_key in ready_keys:
            if memory_key in self._package_icon_ready:
                self._discard_wrench_gallery(memory_key[0])
            if (
                memory_key not in self._package_icon_ready
                or memory_key in self._package_icon_images
                or memory_key in self._package_icon_misses
                or memory_key in self._icon_memory_load_pending
            ):
                continue
            self._icon_memory_load_queue.append(memory_key)
            self._icon_memory_load_pending.add(memory_key)
        self._prioritize_visible_ready_icon_memory_load()
        if self._icon_memory_load_queue and self._icon_memory_load_after_id is None:
            self._icon_memory_load_after_id = self.root.after(
                delay_ms, self._load_ready_icons_into_memory
            )

    def _prioritize_visible_ready_icon_memory_load(self) -> None:
        """Put the current viewport first and paint already-decoded images immediately."""

        self._cancel_after_id("_icon_memory_priority_after_id")
        if self._closing or not hasattr(self, "tree"):
            return
        if self._native_window_interaction_active():
            self._icon_memory_priority_after_id = self.root.after(
                WINDOW_DRAG_BUSY_ANIMATION_POLL_MS,
                self._prioritize_visible_ready_icon_memory_load,
            )
            return
        visible_keys = self._visible_tree_item_keys()
        if not visible_keys:
            return
        current_size = max(12, self.visuals.px(PACKAGE_ICON_SIZE_DIP))
        current_mode = self.palette["mode"]
        for item_key in visible_keys:
            if self._tree_icon_kind.get(item_key) == "app":
                continue
            memory_key = (item_key, current_size, current_mode)
            image = self._package_icon_images.get(memory_key)
            if image is not None and self.tree.exists(item_key):
                if self._tree_icon_kind.get(item_key) != "app":
                    item = self.items.get(item_key)
                    getattr(self, "_tree_row_presentations", {}).pop(item_key, None)
                    self.tree.item(item_key, image=self._presentation_icon(item, image, current_size) if item else image, text="")
                    self._tree_icon_kind[item_key] = "app"
                continue
            if (
                memory_key in self._package_icon_ready
                and memory_key not in self._package_icon_misses
                and memory_key not in self._icon_memory_load_pending
            ):
                self._icon_memory_load_queue.appendleft(memory_key)
                self._icon_memory_load_pending.add(memory_key)
        if self._icon_memory_load_queue:
            # Repartition the existing queue too: rapid scrolling can move the
            # viewport several screens while hundreds of warm icons decode.
            visible: deque[tuple[str, int, str]] = deque()
            remaining: deque[tuple[str, int, str]] = deque()
            while self._icon_memory_load_queue:
                memory_key = self._icon_memory_load_queue.popleft()
                (visible if memory_key[0] in visible_keys else remaining).append(
                    memory_key
                )
            visible.extend(remaining)
            self._icon_memory_load_queue = visible
        if self._icon_memory_load_queue and self._icon_memory_load_after_id is None:
            self._icon_memory_load_after_id = self.root.after(
                0, self._load_ready_icons_into_memory
            )

    def _visible_tree_item_keys(self) -> set[str]:
        """Approximate the current viewport without forcing Tk geometry work."""

        if not hasattr(self, "tree"):
            return set()
        rows = getattr(self, "_tree_display_order", None)
        if rows is None:
            rows = self.tree.get_children()
        if not rows:
            return set()
        try:
            top_fraction, _bottom_fraction = self.tree.yview()
            tree_height = self.tree.winfo_height()
        except Exception:
            top_fraction, tree_height = 0.0, 0
        row_height = max(1, self.visuals.px(UPDATE_ROW_HEIGHT_DIP))
        visible_count = max(8, int(tree_height / row_height) + 8)
        start = max(0, int(top_fraction * len(rows)) - 4)
        stop = min(len(rows), start + visible_count)
        return {str(row) for row in rows[start:stop]}

    def _load_ready_icons_into_memory(self) -> None:
        """Decode cached icons in short Tk-safe batches and paint every matching row."""

        self._icon_memory_load_after_id = None
        if self._closing or not hasattr(self, "tree"):
            return
        if self._native_window_interaction_active():
            self._icon_memory_load_after_id = self.root.after(
                WINDOW_DRAG_BUSY_ANIMATION_POLL_MS, self._load_ready_icons_into_memory
            )
            return
        current_size = max(12, self.visuals.px(PACKAGE_ICON_SIZE_DIP))
        current_mode = self.palette["mode"]
        started = time.perf_counter()
        processed = 0
        limit = self._icon_slice_limit("memory")
        while self._icon_memory_load_queue:
            memory_key = self._icon_memory_load_queue.popleft()
            self._icon_memory_load_pending.discard(memory_key)
            item_key, size, palette_mode = memory_key
            if (
                size != current_size
                or palette_mode != current_mode
                or memory_key not in self._package_icon_ready
                or memory_key in self._package_icon_images
                or memory_key in self._package_icon_misses
            ):
                continue
            item = self.items.get(item_key)
            if item is None:
                continue
            image = self._item_icon_if_ready(item)
            if image is not None and self.tree.exists(item_key):
                getattr(self, "_tree_row_presentations", {}).pop(item_key, None)
                self.tree.item(item_key, image=image, text="")
                self._tree_icon_kind[item_key] = "app"
            processed += 1
            if (
                processed >= limit
                or time.perf_counter() - started >= ICON_SLICE_BUDGET_SECONDS
            ):
                break
        self._note_icon_slice(time.perf_counter() - started, processed, "memory")
        if self._icon_memory_load_queue:
            self._icon_memory_load_after_id = self.root.after(1, self._load_ready_icons_into_memory)
        elif processed and self._icon_sort_active:
            self._schedule_icon_sort_refresh()

    def _reset_ready_icon_memory_load(self) -> None:
        self._cancel_after_id("_icon_memory_load_after_id")
        self._cancel_after_id("_icon_memory_priority_after_id")
        self._icon_memory_load_queue.clear()
        self._icon_memory_load_pending.clear()

    def _reset_background_icon_sweep(self) -> None:
        self._cancel_after_id("_icon_background_sweep_after_id")
        self._cancel_after_id("_icon_background_progress_after_id")
        self._icon_background_sweep_queue.clear()
        self._icon_background_sweep_pending.clear()
        self._icon_background_sweep_active = False
        self._icon_background_sweep_total = 0

    def _background_icon_counts(self) -> tuple[int, int]:
        size = max(12, self.visuals.px(PACKAGE_ICON_SIZE_DIP))
        palette_mode = self.palette["mode"]
        ready = fallback = 0
        for item in self.items.values():
            memory_key = (item.key, size, palette_mode)
            if memory_key in self._package_icon_images or memory_key in self._package_icon_ready:
                ready += 1
            elif memory_key in self._package_icon_misses:
                fallback += 1
        return ready, fallback

    def _report_background_icon_progress(self) -> None:
        self._icon_background_progress_after_id = None
        if self._closing or not self._icon_background_sweep_active:
            return
        ready, fallback = self._background_icon_counts()
        resolved = min(self._icon_background_sweep_total, ready + fallback)
        self._append_log(
            f"Icons: {resolved}/{self._icon_background_sweep_total} checked; "
            f"{ready} ready, {fallback} generated fallbacks"
        )
        self.logger.event(
            "background_icon_sweep_progress",
            total=self._icon_background_sweep_total,
            resolved=resolved,
            ready=ready,
            provider_markers=fallback,
        )
        self._icon_background_progress_after_id = self.root.after(
            ICON_BACKGROUND_PROGRESS_MS,
            self._report_background_icon_progress,
        )

    def _finish_background_icon_sweep_if_idle(self) -> bool:
        if not self._icon_background_sweep_active or self._icon_background_sweep_queue:
            return False
        list_icon_inflight = any(
            not key[0].startswith("details:") for key in self._icon_prepare_inflight
        )
        if list_icon_inflight:
            return False
        self._icon_background_sweep_active = False
        self._cancel_after_id("_icon_background_progress_after_id")
        ready, fallback = self._background_icon_counts()
        parts = [f"{ready} app icons"]
        if fallback:
            parts.append(f"{fallback} using generated fallbacks")
        if self._lazy_icon_batch_upscaled:
            parts.append(f"{self._lazy_icon_batch_upscaled} newly upscaled")
        self._append_log("Icons ready: " + "; ".join(parts) + ".")
        self.logger.event(
            "background_icon_sweep_finished",
            total=self._icon_background_sweep_total,
            ready=ready,
            provider_markers=fallback,
            prepared=self._lazy_icon_batch_cached,
            upscaled=self._lazy_icon_batch_upscaled,
            skipped=self._lazy_icon_batch_failed,
        )
        if self._icon_sort_active:
            self._schedule_icon_sort_refresh()
        self._lazy_icon_batch_active = False
        self._schedule_icon_catalog_write()
        self._start_background_details_icon_sweep()
        return True

    def _reset_background_details_icon_sweep(self) -> None:
        self._details_background_generation += 1
        self._cancel_after_id("_details_background_after_id")
        self._cancel_after_id("_details_background_progress_after_id")
        self._details_background_queue.clear()
        self._details_background_active = False
        self._details_background_inflight = False
        self._details_background_total = 0
        self._details_background_ready = 0
        self._details_background_failed = 0
        self._details_background_signature = ""

    def _start_background_details_icon_sweep(self) -> None:
        """Prepare large Details artwork only after the list-icon phase completes."""

        self._reset_background_details_icon_sweep()
        if (
            self._closing
            or not self.items
            or self._cache_clear_inflight
            or self._portable_local_refresh_active
            or self._portable_local_refresh_pending
        ):
            return
        size = max(48, self.visuals.px(DETAIL_ICON_SIZE_DIP))
        candidates = tuple(
            sorted(
                (
                    (
                        item.key,
                        item.provider,
                        item.package_id,
                        item.name,
                        source,
                    )
                    for item in self.items.values()
                    if (source := self._known_item_icon_source_path(item)) is not None
                ),
                key=lambda record: (
                    record[1] == PORTABLE_PROVIDER_KEY,
                    record[0],
                ),
            )
        )
        if candidates and self._icon_catalog_loaded:
            catalog_ready = 0
            catalog_unavailable = 0
            catalog_complete = True
            for item_key, _provider, _package_id, _name, source in candidates:
                item = self.items[item_key]
                entry = self._icon_catalog_entries.get(item_key)
                record = entry.get("details") if isinstance(entry, dict) else None
                display_path = ""
                if isinstance(record, dict) and record.get("size") == size:
                    display_path = str(icon_cache_dir() / str(record.get("display", "")))
                if (
                    isinstance(entry, dict)
                    and entry.get("identity") == list(item_icon_identity(item))
                    and entry.get("source") == str(source)
                    and display_path in self._icon_catalog_valid_paths
                ):
                    catalog_ready += 1
                elif (
                    isinstance(entry, dict)
                    and entry.get("identity") == list(item_icon_identity(item))
                    and entry.get("source") == str(source)
                    and icon_catalog_miss_is_current(entry, "details")
                ):
                    catalog_unavailable += 1
                else:
                    catalog_complete = False
                    break
            if catalog_complete:
                self._details_background_completed_ready = catalog_ready
                self._details_background_completed_failed = catalog_unavailable
                self.logger.event(
                    "background_details_icon_catalog_reused",
                    total=len(candidates),
                    ready=catalog_ready,
                    unavailable=catalog_unavailable,
                )
                self._schedule_idle_date_sleuth()
                return
        self._details_background_active = bool(candidates)
        self._details_background_inflight = bool(candidates)
        self._details_background_total = len(candidates)
        if not candidates:
            self._append_log("Large icons: no local app artwork found.")
            self._schedule_icon_catalog_write()
            return
        self._details_background_progress_after_id = self.root.after(
            ICON_BACKGROUND_PROGRESS_MS,
            self._report_background_details_icon_progress,
        )
        generation = self._icon_prepare_generation
        sweep_generation = self._details_background_generation
        completed_signature = self._details_background_completed_signature
        completed_ready = self._details_background_completed_ready
        completed_failed = self._details_background_completed_failed

        def worker() -> None:
            records: list[tuple[str, Path]] = []
            signature_hash = hashlib.sha256()
            signature_hash.update(f"details-cache\0{size}\0".encode())
            for item_key, provider, package_id, name, source in candidates:
                raw_path = details_icon_cache_path_for_fields(
                    provider,
                    package_id,
                    name,
                    source,
                    size,
                )
                records.append((item_key, raw_path))
                signature_hash.update(item_key.encode("utf-8", errors="replace"))
                signature_hash.update(b"\0")
                signature_hash.update(str(raw_path).encode("utf-8", errors="replace"))
                signature_hash.update(b"\0")
            signature = signature_hash.hexdigest()
            if signature == completed_signature:
                self.events.put(
                    (
                        "details_icon_cache_indexed",
                        (
                            signature,
                            True,
                            completed_ready,
                            completed_failed,
                            [],
                            generation,
                            sweep_generation,
                        ),
                    )
                )
                return
            ready_count = 0
            unavailable_count = 0
            pending_by_raw_path: dict[Path, list[str]] = {}
            raw_states: dict[Path, str] = {}
            for item_key, raw_path in records:
                state = raw_states.get(raw_path)
                if state is None:
                    if rendered_icon_cache_is_current(raw_path, size):
                        state = "ready"
                    elif icon_render_miss_is_current(raw_path, size):
                        state = "unavailable"
                    else:
                        state = "pending"
                    raw_states[raw_path] = state
                if state == "ready":
                    ready_count += 1
                elif state == "unavailable":
                    unavailable_count += 1
                else:
                    pending_by_raw_path.setdefault(raw_path, []).append(item_key)
            pending_groups = [
                (item_keys[0], tuple(item_keys))
                for item_keys in pending_by_raw_path.values()
                if item_keys
            ]
            self.logger.event(
                "source_versioned_raw_icon_plan",
                presentation="details",
                references=len(records),
                unique_raw_paths=len({raw_path for _item_key, raw_path in records}),
                pending_references=sum(len(keys) for keys in pending_by_raw_path.values()),
                pending_raw_jobs=len(pending_groups),
                duplicate_jobs_avoided=max(
                    0,
                    sum(len(keys) for keys in pending_by_raw_path.values())
                    - len(pending_groups),
                ),
            )
            self.events.put(
                (
                    "details_icon_cache_indexed",
                    (
                        signature,
                        False,
                        ready_count,
                        unavailable_count,
                        pending_groups,
                        generation,
                        sweep_generation,
                    ),
                )
            )

        threading.Thread(target=worker, name="wdp-details-icon-index", daemon=True).start()

    def _finish_background_details_icon_index(
        self,
        signature: str,
        unchanged: bool,
        ready_count: int,
        unavailable_count: int,
        pending_groups: list[tuple[str, tuple[str, ...]]],
        generation: int,
        sweep_generation: int,
    ) -> None:
        if (
            generation != self._icon_prepare_generation
            or sweep_generation != self._details_background_generation
        ):
            return
        self._details_background_inflight = False
        if self._closing or not self._details_background_active:
            return
        self._details_background_signature = signature
        self._details_background_ready = ready_count
        self._details_background_failed = unavailable_count
        if unchanged:
            self._details_background_active = False
            self._cancel_after_id("_details_background_progress_after_id")
            self.logger.event(
                "background_details_icon_cache_reused",
                total=self._details_background_total,
                ready=ready_count,
                unavailable=unavailable_count,
            )
            self._schedule_icon_catalog_write()
            self._schedule_idle_date_sleuth()
            return
        for _representative, aliases in pending_groups:
            live_aliases = tuple(key for key in aliases if key in self.items)
            if live_aliases:
                self._details_background_queue.append((live_aliases[0], live_aliases))
        pending_references = sum(
            len(aliases) for _representative, aliases in self._details_background_queue
        )
        self.logger.event(
            "background_details_icon_cache_indexed",
            total=self._details_background_total,
            ready=ready_count,
            unavailable=unavailable_count,
            needs_preparation=len(self._details_background_queue),
            pending_references=pending_references,
            duplicate_jobs_avoided=max(
                0, pending_references - len(self._details_background_queue)
            ),
        )
        if self._details_background_queue:
            self._append_log(
                f"Package Details icon cache: {ready_count} ready"
                + (f", {unavailable_count} recently unavailable" if unavailable_count else "")
                + "; "
                f"preparing {len(self._details_background_queue)} unique missing or stale "
                f"source(s) for {pending_references} package row(s)",
                show_in_ui=False,
            )
            self._schedule_background_details_icon_sweep()
        else:
            self._finish_background_details_icon_sweep_if_idle()

    def _report_background_details_icon_progress(self) -> None:
        self._details_background_progress_after_id = None
        if self._closing or not self._details_background_active:
            return
        resolved = self._details_background_ready + self._details_background_failed
        self._append_log(
            f"Large icons: {resolved}/{self._details_background_total} checked; "
            f"{self._details_background_ready} ready, "
            f"{self._details_background_failed} unavailable"
        )
        self.logger.event(
            "background_details_icon_progress",
            total=self._details_background_total,
            resolved=resolved,
            ready=self._details_background_ready,
            failed=self._details_background_failed,
        )
        self._details_background_progress_after_id = self.root.after(
            ICON_BACKGROUND_PROGRESS_MS,
            self._report_background_details_icon_progress,
        )

    def _finish_background_details_icon_sweep_if_idle(self) -> bool:
        if (
            not self._details_background_active
            or self._details_background_queue
            or self._details_background_inflight
        ):
            return False
        self._details_background_active = False
        self._cancel_after_id("_details_background_progress_after_id")
        self._details_background_completed_signature = self._details_background_signature
        self._details_background_completed_ready = self._details_background_ready
        self._details_background_completed_failed = self._details_background_failed
        unavailable = max(
            0,
            len(self.items) - self._details_background_ready,
        )
        parts = [f"{self._details_background_ready} app icons"]
        if unavailable:
            parts.append(f"{unavailable} using provider artwork")
        self._append_log("Large icons ready: " + "; ".join(parts) + ".")
        self.logger.event(
            "background_details_icon_finished",
            total=self._details_background_total,
            ready=self._details_background_ready,
            failed=self._details_background_failed,
            provider_artwork=unavailable,
        )
        self._schedule_icon_catalog_write()
        self._schedule_idle_date_sleuth()
        return True

    def _reset_idle_date_sleuth(self) -> None:
        self._date_sleuth_generation += 1
        self._date_sleuth_active = False
        self._cancel_after_id("_date_sleuth_after_id")

    def _date_sleuth_can_start(self) -> bool:
        """Reserve filesystem date inference for the absolute back of the queue."""

        return bool(
            not self._closing
            and self._last_scan_completed_at is not None
            and not self.busy
            and not self._scan_active
            and not self._winget_enrichment_active
            and not self._portable_scan_active
            and not self._portable_cache_verification_active
            and not self._portable_local_refresh_active
            and not self._portable_local_refresh_pending
            and not self._portable_catalog_refresh_active
            and not self._cache_clear_inflight
            and not self._diagnostic_bundle_inflight
            and not self._lazy_icon_batch_active
            and not self._icon_background_sweep_active
            and not self._details_background_active
            and not self._details_background_inflight
            and not self._icon_prepare_inflight
            and not self._icon_gallery_active_jobs
            and not self._icon_catalog_write_active
            and not self._icon_catalog_write_pending
            and not self._icon_catalog_write_lock.locked()
            and self.icon_renderer.wait_idle(0.0)
        )

    def _schedule_idle_date_sleuth(
        self,
        delay_ms: int = IDLE_DATE_SLEUTH_DELAY_MS,
    ) -> None:
        if (
            self._closing
            or self._date_sleuth_active
            or self._date_sleuth_after_id is not None
        ):
            return
        self._date_sleuth_after_id = self.root.after(
            delay_ms,
            self._run_idle_date_sleuth,
        )

    def _date_sleuth_signature(self) -> str:
        digest = hashlib.sha256(b"idle-date-sleuth-v2\0")
        catalog = self._scan_view_items[True]
        for item in sorted(catalog.values(), key=installed_item_date_identity):
            appx_candidate = (
                item.package_id.casefold().startswith("msix\\")
                and (not item.installed_timestamp or item.installed_date_is_estimate)
            )
            portable_candidate = (
                item.provider == PORTABLE_PROVIDER_KEY
                and not item.installed_timestamp
                and bool(item.portable_executable)
            )
            if (
                (
                    (item.installed_timestamp or item.installed_date)
                    and not appx_candidate
                    and not portable_candidate
                )
                or (
                    item.provider != WingetProvider.key
                    and not portable_candidate
                )
            ):
                continue
            digest.update("\0".join(installed_item_date_identity(item)).encode("utf-8"))
            digest.update(b"\0")
            digest.update(item.installed_location.encode("utf-8", errors="replace"))
            digest.update(b"\0")
            digest.update(item.icon_source.encode("utf-8", errors="replace"))
            digest.update(b"\0")
            if portable_candidate:
                digest.update(
                    item.portable_executable.encode("utf-8", errors="replace")
                )
                digest.update(b"\0")
        return digest.hexdigest()

    def _run_idle_date_sleuth(self) -> None:
        self._date_sleuth_after_id = None
        if self._closing or self._date_sleuth_active:
            return
        if not self._date_sleuth_can_start():
            self._schedule_idle_date_sleuth()
            return
        signature = self._date_sleuth_signature()
        if signature == self._date_sleuth_completed_signature:
            return
        seen: set[tuple[str, str, str, str, str]] = set()
        snapshots: list[UpdateItem] = []
        for item in self._scan_view_items[True].values():
            identity = installed_item_date_identity(item)
            appx_candidate = (
                item.package_id.casefold().startswith("msix\\")
                and (not item.installed_timestamp or item.installed_date_is_estimate)
            )
            portable_candidate = (
                item.provider == PORTABLE_PROVIDER_KEY
                and not item.installed_timestamp
                and bool(item.portable_executable)
            )
            if (
                identity in seen
                or (
                    (item.installed_timestamp or item.installed_date)
                    and not appx_candidate
                    and not portable_candidate
                )
                or (
                    item.provider != WingetProvider.key
                    and not portable_candidate
                )
                or (
                    not appx_candidate
                    and not portable_candidate
                    and not item.installed_location
                )
            ):
                continue
            seen.add(identity)
            # Resolved artwork may be shared branding or a similarly named CLI.
            # It must not become installation evidence in this worker.
            snapshots.append(dataclasses.replace(item))
        if not snapshots:
            self._date_sleuth_completed_signature = signature
            return
        generation = self._date_sleuth_generation
        self._date_sleuth_active = True

        def preempted() -> bool:
            return (
                self._closing
                or generation != self._date_sleuth_generation
                or not self._date_sleuth_can_start()
            )

        def worker_body() -> None:
            results: list[
                tuple[
                    tuple[str, str, str, str, str],
                    str,
                    str,
                    str,
                    bool,
                    str,
                    tuple[str, ...],
                ]
            ] = []
            checked = 0
            interrupted = False
            appx_dates: dict[str, tuple[str, str]] = {}
            appx_error = ""
            local_date_cache: dict[tuple[str, ...], tuple[str, tuple[str, ...]]] = {}
            if any(snapshot.package_id.casefold().startswith("msix\\") for snapshot in snapshots):
                appx_dates, appx_error = windows_app_package_installed_dates()
            for snapshot in snapshots:
                if preempted():
                    interrupted = True
                    break
                if snapshot.provider == PORTABLE_PROVIDER_KEY:
                    checked += 1
                    (
                        installed_date,
                        installed_timestamp,
                        date_source,
                        evidence_paths,
                    ) = portable_executable_service_date(
                        snapshot.portable_executable,
                        app_name=snapshot.name,
                        original_filename=snapshot.portable_original_filename,
                        scan_root=snapshot.portable_scan_root,
                    )
                    if installed_date:
                        results.append(
                            (
                                installed_item_date_identity(snapshot),
                                installed_date,
                                installed_timestamp,
                                "fractional-6" if installed_timestamp else "date",
                                True,
                                date_source,
                                evidence_paths,
                            )
                        )
                    continue
                if snapshot.package_id.casefold().startswith("msix\\"):
                    full_name = snapshot.package_id.split("\\", 1)[1].casefold()
                    if installed_time := appx_dates.get(full_name):
                        installed_timestamp, installed_precision = installed_time
                        installed_date = (
                            dt.datetime.fromisoformat(installed_timestamp)
                            .astimezone()
                            .date()
                            .isoformat()
                        )
                        results.append(
                            (
                                installed_item_date_identity(snapshot),
                                installed_date,
                                installed_timestamp,
                                installed_precision,
                                False,
                                "Windows Package.InstalledDate (installed or last updated)",
                                (),
                            )
                        )
                        continue
                if snapshot.installed_timestamp:
                    continue
                paths = local_date_sleuth_paths(snapshot)
                if len(paths) < 2:
                    continue
                checked += 1
                path_key = tuple(
                    os.path.normcase(os.path.normpath(str(path))) for path in paths
                )
                cached_date = local_date_cache.get(path_key)
                if cached_date is None:
                    cached_date = corroborated_local_service_date(paths)
                    local_date_cache[path_key] = cached_date
                installed_date, installed_timestamp, evidence_paths = cached_date
                if installed_date:
                    results.append(
                        (
                            installed_item_date_identity(snapshot),
                            installed_date,
                            installed_timestamp,
                            "fractional-6" if installed_timestamp else "date",
                            True,
                            (
                                "Corroborated local install-folder creation times "
                                "(approximate; not the original installation date)"
                            ),
                            evidence_paths,
                        )
                    )
            self.events.put(
                (
                    "idle_dates_done",
                    (generation, signature, checked, results, interrupted, appx_error),
                )
            )

        def worker() -> None:
            try:
                worker_body()
            except Exception as exc:
                self.events.put(
                    (
                        "idle_dates_done",
                        (
                            generation,
                            signature,
                            0,
                            (),
                            False,
                            f"date evidence worker failed: {type(exc).__name__}: {exc}",
                        ),
                    )
                )

        threading.Thread(
            target=worker,
            name="wdp-idle-date-sleuth",
            daemon=True,
        ).start()

    def _finish_idle_date_sleuth(
        self,
        generation: int,
        signature: str,
        checked: int,
        results: Sequence[
            tuple[
                tuple[str, str, str, str, str],
                str,
                str,
                str,
                bool,
                str,
                tuple[str, ...],
            ]
        ],
        interrupted: bool,
        appx_error: str,
    ) -> None:
        if generation != self._date_sleuth_generation or self._closing:
            return
        self._date_sleuth_active = False
        if (
            interrupted
            or not self._date_sleuth_can_start()
            or signature != self._date_sleuth_signature()
        ):
            self._schedule_idle_date_sleuth()
            return
        by_identity = {
            identity: (value, timestamp, precision, estimate, source, paths)
            for identity, value, timestamp, precision, estimate, source, paths in results
        }
        changed_keys: set[str] = set()
        applied_keys: set[str] = set()
        applied_identities: set[tuple[str, str, str, str, str]] = set()
        portable_date_evidence: dict[
            str, tuple[str, str, str, str, tuple[str, ...]]
        ] = {}
        seen_objects: set[int] = set()
        for catalog in (*self._scan_view_items.values(), self.items):
            for item in catalog.values():
                if id(item) in seen_objects:
                    continue
                seen_objects.add(id(item))
                identity = installed_item_date_identity(item)
                evidence = by_identity.get(identity)
                if evidence is None:
                    continue
                if item.installed_timestamp and not item.installed_date_is_estimate:
                    continue
                item.installed_date = evidence[0]
                item.installed_timestamp = evidence[1]
                item.installed_timestamp_precision = evidence[2]
                item.installed_date_is_estimate = evidence[3]
                item.installed_date_source = evidence[4]
                if item.provider == PORTABLE_PROVIDER_KEY and item.portable_executable:
                    portable_date_evidence[item.portable_executable] = (
                        evidence[0],
                        evidence[1],
                        evidence[2],
                        evidence[4],
                        evidence[5],
                    )
                applied_identities.add(identity)
                applied_keys.add(item.key)
                if item.key in self.items:
                    changed_keys.add(item.key)
        self._date_sleuth_completed_signature = self._date_sleuth_signature()
        approximate_applied = sum(by_identity[identity][3] for identity in applied_identities)
        exact_applied = len(applied_identities) - approximate_applied
        if changed_keys:
            if self._sort_state and self._sort_state[0] == "installed_date":
                self._rebuild_tree()
            else:
                for key in changed_keys:
                    item = self.items.get(key)
                    if item is not None:
                        self._refresh_item_row(item)
        if applied_keys:
            for listener in tuple(self._details_refinement_listeners):
                for key in applied_keys:
                    with contextlib.suppress(Exception):
                        listener(key)
            parts = []
            if exact_applied:
                parts.append(f"{exact_applied} from Windows package metadata")
            if approximate_applied:
                parts.append(f"{approximate_applied} approximate from local evidence")
            self._append_log("Install/service dates enriched at idle: " + "; ".join(parts))
        self.logger.event(
            "idle_date_sleuth_finished",
            checked=checked,
            inferred=len(results),
            applied=len(applied_identities),
            exact_applied=exact_applied,
            approximate_applied=approximate_applied,
            appx_error=appx_error,
            evidence=[
                {
                    "identity": identity,
                    "date": value,
                    "timestamp": timestamp,
                    "timestamp_precision": precision,
                    "approximate": estimate,
                    "source": source,
                    "paths": list(paths),
                }
                for identity, value, timestamp, precision, estimate, source, paths in results
            ],
        )
        if appx_error:
            self._append_log(
                f"Install/service date check warning: {appx_error}",
                show_in_ui=False,
            )
        snapshot = self._observation_inventory_snapshot
        if applied_keys and snapshot.scanned_at is not None:
            enriched = tuple(dataclasses.replace(item) for item in snapshot.items)
            if reuse_cached_service_dates(enriched, tuple(self._scan_view_items[True].values())):
                self._observation_inventory_snapshot = dataclasses.replace(snapshot, items=enriched)
                self._write_installed_inventory_cache_async(
                    self._observation_inventory_snapshot, self._active_scan_generation,
                )
        if portable_date_evidence:
            detached_evidence = dict(portable_date_evidence)

            def persist_portable_dates() -> None:
                try:
                    changed = self.portable_inventory.update_date_evidence(
                        detached_evidence
                    )
                    self.logger.event(
                        "portable_date_evidence_cached",
                        candidate_count=len(detached_evidence),
                        changed=changed,
                    )
                except Exception as exc:
                    self.logger.event(
                        "portable_date_evidence_cache_failed",
                        error=f"{type(exc).__name__}: {exc}",
                    )

            threading.Thread(
                target=persist_portable_dates,
                name="wdp-portable-date-cache",
                daemon=True,
            ).start()

    def _schedule_background_details_icon_sweep(
        self,
        delay_ms: int = ICON_BACKGROUND_SWEEP_DELAY_MS,
    ) -> None:
        if (
            self._closing
            or not self._details_background_active
            or self._details_background_after_id is not None
        ):
            return
        self._details_background_after_id = self.root.after(
            delay_ms,
            self._run_background_details_icon_sweep,
        )

    def _run_background_details_icon_sweep(self) -> None:
        self._details_background_after_id = None
        if self._closing or not self._details_background_active:
            return
        if not self._details_background_queue:
            self._finish_background_details_icon_sweep_if_idle()
            return
        self._paint_resident_visible_icons()
        quiet_remaining = self._icon_scroll_quiet_until - time.monotonic()
        if self._icon_speculation_paused():
            delay_ms = (
                max(ICON_BACKGROUND_SWEEP_SCROLL_DELAY_MS, int(quiet_remaining * 1000) + 40)
                if quiet_remaining > 0
                else ICON_BACKGROUND_SWEEP_SCROLL_DELAY_MS
            )
            self._schedule_background_details_icon_sweep(delay_ms)
            return
        if self._details_background_inflight:
            return
        _queued_item_key, alias_keys = self._details_background_queue.popleft()
        live_alias_keys = tuple(key for key in alias_keys if key in self.items)
        if not live_alias_keys:
            self._schedule_background_details_icon_sweep()
            return
        item_key = live_alias_keys[0]
        item = self.items[item_key]
        size = max(48, self.visuals.px(DETAIL_ICON_SIZE_DIP))
        generation = self._icon_prepare_generation
        sweep_generation = self._details_background_generation
        revisions = {key: getattr(self, "_icon_item_revisions", {}).get(key, 0)
                     for key in live_alias_keys}
        alias_snapshots = tuple(dataclasses.replace(self.items[key]) for key in live_alias_keys)
        list_size = max(12, self.visuals.px(PACKAGE_ICON_SIZE_DIP))
        self._details_background_inflight = True

        def worker(snapshot: UpdateItem) -> None:
            ok = False
            source: Path | None = None
            failure_reason = ""
            resident_entries: dict[str, dict[str, Any]] = {}
            resident_blobs: dict[str, bytes] = {}
            try:
                ok, source = self._prepare_details_icon_cache_file(
                    snapshot,
                    size,
                    generation,
                    f"prefetch:{snapshot.key}",
                    priority=20,
                )
                if not ok:
                    failure_reason = "no usable large icon could be prepared"
                elif source is not None:
                    resident_entries, resident_blobs = prepared_details_icon_payload(
                        alias_snapshots, source, list_size, size)
            except Exception as exc:
                failure_reason = f"{type(exc).__name__}: {exc}"
            self.events.put(
                (
                    "details_icon_prefetched",
                    (
                        snapshot.key,
                        live_alias_keys,
                        ok,
                        source,
                        generation,
                        sweep_generation,
                        failure_reason,
                        revisions,
                        resident_entries,
                        resident_blobs,
                    ),
                )
            )

        threading.Thread(
            target=worker,
            args=(dataclasses.replace(item),),
            name="wdp-details-icon-prefetch",
            daemon=True,
        ).start()

    def _publish_resident_details_icon(
        self, item: UpdateItem, source: Path | None,
        entry: Mapping[str, Any] | None, blobs: Mapping[str, bytes],
    ) -> None:
        """Admit worker-validated bytes on Tk without probing files or decoding."""
        if (not entry or entry.get("identity") != list(item_icon_identity(item))
                or entry.get("version") != item.current or entry.get("source") != str(source)):
            return
        record = entry.get("details")
        if not isinstance(record, dict) or record.get("size") != max(48, self.visuals.px(DETAIL_ICON_SIZE_DIP)):
            return
        if source is not None:
            self._remember_details_icon_evidence(item, int(record["size"]), source, entry.get("details_evidence"))
        path = str(icon_cache_dir() / record["display"])
        data = blobs.get(path)
        if data is None or not self._admit_icon_blob(path, data):
            return
        previous = self._icon_catalog_entries.get(item.key, {})
        if previous.get("compact", {}).get("parent_stat") != entry.get("compact", {}).get("parent_stat"):
            compact_key = (item.key, compact_gallery_size(record["size"]), self.palette["mode"])
            self._compact_icon_images.pop(compact_key, None)
            self._compact_icon_tokens.pop(compact_key, None)
        merged = dict(entry)
        merged.pop("details_evidence", None)
        if (previous.get("identity") == entry["identity"]
                and previous.get("version") == entry["version"]
                and previous.get("source_stat") == entry["source_stat"]
                and previous.get("source") == entry["source"]
                and "list" not in merged and "list" in previous):
            merged["list"] = previous["list"]
        self._icon_catalog_entries[item.key] = merged
        self._icon_catalog_valid_paths.add(path)
        compact = entry.get("compact")
        if isinstance(compact, dict):
            compact_path = str(icon_cache_dir() / compact["display"])
            if compact_path in blobs and self._admit_icon_blob(compact_path, blobs[compact_path]):
                self._icon_catalog_valid_paths.add(compact_path)
                self._icon_catalog_decode_queue.append((item.key, compact["size"], compact_path))
                self._catalog_decode_priority = None
                if self._icon_catalog_decode_after_id is None:
                    self._icon_catalog_decode_after_id = self.root.after(1, self._decode_catalog_icons)

    def _finish_background_details_icon_prepare(
        self,
        item_key: str,
        alias_keys: tuple[str, ...],
        ok: bool,
        source: Path | None,
        generation: int,
        sweep_generation: int,
        failure_reason: str,
        revisions: Mapping[str, int] | None = None,
        resident_entries: Mapping[str, Mapping[str, Any]] | None = None,
        resident_blobs: Mapping[str, bytes] | None = None,
    ) -> None:
        if (
            self._closing or generation != self._icon_prepare_generation
            or sweep_generation != self._details_background_generation
        ):
            return
        self._details_background_inflight = False
        if not self._details_background_active:
            return
        live_alias_keys = tuple(key for key in alias_keys if key in self.items
                                and (revisions is None or revisions.get(key, 0)
                                     == getattr(self, "_icon_item_revisions", {}).get(key, 0)))
        if source is not None:
            for alias_key in live_alias_keys:
                self._item_icon_source_cache[alias_key] = source
        resolved_count = len(live_alias_keys)
        if ok:
            self._details_background_ready += resolved_count
            for alias_key in live_alias_keys:
                item = self.items[alias_key]
                self._publish_resident_details_icon(
                    item, source, (resident_entries or {}).get(alias_key), resident_blobs or {})
            self._enqueue_gallery_idle_promotions()
            if getattr(self, "_package_gallery_mode", False):
                for alias_key in live_alias_keys:
                    self._package_gallery_icon_ready(alias_key, self._package_gallery_icon_token(alias_key))
        else:
            self._details_background_failed += resolved_count
            item = self.items.get(item_key)
            self.logger.event(
                "background_details_icon_prepare_failed",
                item_key=item_key,
                package_id=item.package_id if item is not None else "",
                provider=item.provider if item is not None else "",
                source=str(source) if source is not None else "",
                reason=failure_reason,
                affected_rows=resolved_count,
            )
        if not self._finish_background_details_icon_sweep_if_idle():
            self._schedule_background_details_icon_sweep()

    def _schedule_background_icon_sweep(
        self,
        *,
        delay_ms: int = ICON_BACKGROUND_SWEEP_DELAY_MS,
        restart: bool = False,
    ) -> None:
        """Prepare every unresolved list icon gradually while the interface is idle."""

        if self._closing or not self.items:
            return
        if restart:
            self._reset_background_icon_sweep()
            visible_order = [str(row) for row in self.tree.get_children()]
            visible_set = set(visible_order)
            candidate_keys = visible_order + [key for key in self.items if key not in visible_set]
            candidate_keys.sort(
                key=lambda key: bool(
                    (item := self.items.get(key))
                    and item.provider == PORTABLE_PROVIDER_KEY
                )
            )
            size = max(12, self.visuals.px(PACKAGE_ICON_SIZE_DIP))
            palette_mode = self.palette["mode"]
            ordered_keys: list[str] = []
            for key in candidate_keys:
                item = self.items.get(key)
                if item is None:
                    continue
                memory_key = (item.key, size, palette_mode)
                if (
                    memory_key in self._package_icon_images
                    or memory_key in self._package_icon_misses
                    or memory_key in self._package_icon_ready
                ):
                    continue
                if (
                    key in self._item_icon_source_cache
                    and self._item_icon_source_cache[key] is None
                ):
                    self._package_icon_misses.add(memory_key)
                    continue
                ordered_keys.append(key)
            self._icon_background_sweep_queue.extend(ordered_keys)
            self._icon_background_sweep_pending.update(ordered_keys)
            self._icon_background_sweep_active = bool(ordered_keys)
            self._icon_background_sweep_total = len(ordered_keys)
            self._lazy_icon_batch_active = bool(ordered_keys)
            self._lazy_icon_batch_cached = 0
            self._lazy_icon_batch_failed = 0
            self._lazy_icon_batch_upscaled = 0
            if not ordered_keys:
                self._lazy_icon_batch_active = False
                self._start_background_details_icon_sweep()
                return
            if ordered_keys:
                self._lazy_icon_log_announced = True
                self._append_log(
                    f"Icons: checking {len(ordered_keys)} package(s)"
                )
                self._icon_background_progress_after_id = self.root.after(
                    ICON_BACKGROUND_PROGRESS_MS,
                    self._report_background_icon_progress,
                )
        if self._icon_background_sweep_queue and self._icon_background_sweep_after_id is None:
            self._icon_background_sweep_after_id = self.root.after(
                delay_ms, self._run_background_icon_sweep
            )

    def _run_background_icon_sweep(self) -> None:
        """Start at most one off-thread icon job, yielding to work and scrolling."""

        self._icon_background_sweep_after_id = None
        if self._closing:
            return
        if not self._icon_background_sweep_queue:
            self._finish_background_icon_sweep_if_idle()
            return
        quiet_remaining = self._icon_scroll_quiet_until - time.monotonic()
        if self.busy or self._cache_clear_inflight or quiet_remaining > 0:
            delay_ms = (
                max(ICON_BACKGROUND_SWEEP_SCROLL_DELAY_MS, int(quiet_remaining * 1000) + 40)
                if quiet_remaining > 0
                else ICON_BACKGROUND_SWEEP_SCROLL_DELAY_MS
            )
            self._schedule_background_icon_sweep(delay_ms=delay_ms)
            return
        if any(not key[0].startswith("details:") for key in self._icon_prepare_inflight):
            self._schedule_background_icon_sweep(delay_ms=90)
            return
        size = max(12, self.visuals.px(PACKAGE_ICON_SIZE_DIP))
        palette_mode = self.palette["mode"]
        while self._icon_background_sweep_queue:
            item_key = self._icon_background_sweep_queue.popleft()
            self._icon_background_sweep_pending.discard(item_key)
            item = self.items.get(item_key)
            if item is None:
                continue
            memory_key = (item.key, size, palette_mode)
            if memory_key in self._package_icon_images or memory_key in self._package_icon_misses:
                continue
            if memory_key in self._package_icon_ready:
                self._schedule_ready_icon_memory_load((memory_key,))
                continue
            if memory_key in self._icon_prepare_inflight:
                self._schedule_background_icon_sweep(delay_ms=90)
                return
            self._queue_icon_prepare(item, size)
            if memory_key in self._icon_prepare_inflight:
                return
        # All work was already cached or classified as a miss.
        self._finish_background_icon_sweep_if_idle()

    def _schedule_visible_icon_hydration(
        self, *, delay_ms: int = 240, restart: bool = False
    ) -> None:
        if self._closing or not hasattr(self, "tree"):
            return
        if self._icon_hydration_after_id is not None:
            if not restart:
                return
            self._cancel_after_id("_icon_hydration_after_id")
        self._icon_hydration_after_id = self.root.after(delay_ms, self._hydrate_visible_icons)

    def _paint_resident_visible_icons(self) -> None:
        """Publish existing list photos during scrolling; no decoding or filesystem work."""
        if (self._closing or not hasattr(self, "tree")
                or getattr(self, "_cache_clear_inflight", False)
                or self._native_window_interaction_active()):
            return
        rows = getattr(self, "_tree_display_order", ())
        if not rows:
            return
        top = self.tree.yview()[0]
        height = max(1, self.visuals.px(UPDATE_ROW_HEIGHT_DIP))
        start = max(0, int(top * len(rows)) - 1)
        count = int(self.tree.winfo_height() / height) + 4
        size, mode = max(12, self.visuals.px(PACKAGE_ICON_SIZE_DIP)), self.palette["mode"]
        for row in rows[start:start + count]:
            if self._tree_icon_kind.get(row) == "app":
                continue
            item = self.items.get(row)
            if item is None:
                continue
            preferred = preferred_vector_style(item)
            image = (self._provider_icon_images.get((preferred, size, mode)) if preferred
                     else self._package_icon_images.get((row, size, mode)))
            if image is not None and self.tree.exists(row):
                getattr(self, "_tree_row_presentations", {}).pop(row, None)
                self.tree.item(row, image=image, text="")
                self._tree_icon_kind[row] = "app"

    def _tree_yscroll(self, scrollbar: Any, *args: Any) -> None:
        scrollbar.set(*args)
        self._note_icon_idle_activity()
        if ((self._icon_memory_load_queue or self._package_icon_ready)
                and self._icon_memory_priority_after_id is None):
            self._icon_memory_priority_after_id = self.root.after(
                0,
                self._prioritize_visible_ready_icon_memory_load,
            )
        if self._hover_row:
            self._tree_leave()
        self._tree_hover_needs_refresh = True
        # Move the deadline, not the timer. The hydration callback rechecks it;
        # a long gesture needs only occasional wakeups, not cancel/rearm per row.
        self._icon_scroll_quiet_until = time.monotonic() + 0.32
        self._paint_resident_visible_icons()
        self._schedule_visible_icon_hydration(delay_ms=340)

    def _tree_scroll_key_pressed(self, _event: Any = None) -> None:
        self._tree_wheel_remainder = 0
        self._cancel_after_id("_icon_key_release_after_id")

    def _tree_scroll_key_released(self, _event: Any = None) -> None:
        self._cancel_after_id("_icon_key_release_after_id")
        self._icon_key_release_after_id = self.root.after(
            ICON_KEY_RELEASE_SETTLE_MS,
            self._finish_tree_key_scroll,
        )

    def _finish_tree_key_scroll(self) -> None:
        self._icon_key_release_after_id = None
        if self._closing:
            return
        self._icon_scroll_quiet_until = 0.0
        self._schedule_visible_icon_hydration(delay_ms=0, restart=True)

    def _hydrate_visible_icons(self) -> None:
        self._icon_hydration_after_id = None
        if self._closing or not hasattr(self, "tree"):
            return
        if self._native_window_interaction_active():
            self._schedule_visible_icon_hydration(
                delay_ms=WINDOW_DRAG_BUSY_ANIMATION_POLL_MS,
                restart=True,
            )
            return
        quiet_remaining = self._icon_scroll_quiet_until - time.monotonic()
        if quiet_remaining > 0:
            self._schedule_visible_icon_hydration(
                delay_ms=max(40, int(quiet_remaining * 1000) + 20), restart=True
            )
            return
        self._refresh_tree_hover_after_scroll()
        rows = self.tree.get_children()
        if not rows:
            return
        try:
            top_fraction, _bottom_fraction = self.tree.yview()
        except Exception:
            top_fraction = 0.0
        row_height = max(1, self.visuals.px(UPDATE_ROW_HEIGHT_DIP))
        visible_count = max(8, int(self.tree.winfo_height() / row_height) + 8)
        start = max(0, int(top_fraction * len(rows)) - 4)
        stop = min(len(rows), start + visible_count)
        hydration_started = time.perf_counter()
        painted = 0
        queued = False
        pending_visible = False
        budget_exhausted = False
        size = max(12, self.visuals.px(PACKAGE_ICON_SIZE_DIP))
        palette_mode = self.palette["mode"]
        for row in rows[start:stop]:
            if not self.tree.bbox(row, "#0"):
                continue
            item = self.items.get(str(row))
            if item is None:
                continue
            if self._tree_icon_kind.get(str(row)) == "app":
                continue
            memory_key = (item.key, size, palette_mode)
            image = self._item_icon_if_ready(item)
            if image is not None:
                getattr(self, "_tree_row_presentations", {}).pop(row, None)
                self.tree.item(row, image=image, text="")
                self._tree_icon_kind[str(row)] = "app"
                painted += 1
            else:
                if self._tree_icon_kind.get(str(row)) != "provider":
                    getattr(self, "_tree_row_presentations", {}).pop(row, None)
                    self.tree.item(row, image=self._fallback_icon(item), text="")
                    self._tree_icon_kind[str(row)] = "provider"
                if memory_key not in self._package_icon_misses and not queued:
                    self._queue_icon_prepare(item, size)
                    queued = memory_key in self._icon_prepare_inflight
                if memory_key not in self._package_icon_misses:
                    pending_visible = True
            if (
                painted >= ICON_HYDRATION_PAINT_LIMIT
                or time.perf_counter() - hydration_started >= ICON_HYDRATION_TIME_BUDGET_SECONDS
            ):
                pending_visible = True
                budget_exhausted = True
                break
        if budget_exhausted:
            self._schedule_visible_icon_hydration(delay_ms=1)
        elif pending_visible and not queued:
            self._schedule_visible_icon_hydration(delay_ms=100)
        if self.busy or queued or pending_visible:
            return
        # Once the viewport is complete and the app is idle, prepare at most
        # one nearby icon per tick. This removes the next-scroll pop-in without
        # turning decoration into speculative whole-list work.
        screen_count = max(8, int(self.tree.winfo_height() / row_height) + 2)
        visible_start = max(0, int(top_fraction * len(rows)))
        visible_stop = min(len(rows), visible_start + screen_count)
        nearby_rows = list(rows[visible_stop : visible_stop + screen_count])
        nearby_rows.extend(reversed(rows[max(0, visible_start - screen_count) : visible_start]))
        for row in nearby_rows:
            item = self.items.get(str(row))
            if item is None:
                continue
            memory_key = (item.key, size, palette_mode)
            if (
                memory_key in self._package_icon_images
                or memory_key in self._package_icon_misses
                or memory_key in self._icon_prepare_inflight
            ):
                continue
            if memory_key in self._package_icon_ready:
                self._item_icon_if_ready(item)
                self._schedule_visible_icon_hydration(delay_ms=90)
                break
            self._queue_icon_prepare(item, size)
            if memory_key in self._icon_prepare_inflight:
                break

    def _refresh_scan_button_style(self) -> None:
        button = getattr(self, "scan_button", None)
        if button is None:
            return
        style = "ScanFresh.TButton" if self._scan_results_current else "ScanStale.TButton"
        can_scan = not self._scan_active and (
            not self.busy or self._busy_kind == "update"
        )
        button.configure(
            style=style,
            text="↻  Scanning…" if self._scan_active else "↻  Scan",
            state="normal" if can_scan else "disabled",
        )

    def _refresh_scan_view_buttons(self) -> None:
        updates = getattr(self, "updates_view_button", None)
        all_packages = getattr(self, "all_packages_view_button", None)
        if updates is not None:
            updates.configure(
                style=(
                    "PrimaryNavActive.TButton"
                    if not self._last_scan_all_packages
                    else "PrimaryNav.TButton"
                )
            )
        if all_packages is not None:
            all_packages.configure(
                style=(
                    "PrimaryNavActive.TButton"
                    if self._last_scan_all_packages
                    else "PrimaryNav.TButton"
                )
            )
        self._schedule_nav_indicator()
        self._refresh_scan_view_mode_controls()

    def _schedule_nav_indicator(self) -> None:
        indicator = getattr(self, "_nav_indicator", None)
        if indicator is None or self._closing:
            return
        self._cancel_after_id("_nav_indicator_after_id")
        self._nav_indicator_after_id = self.root.after_idle(
            self._position_nav_indicator
        )

    def _position_nav_indicator(self) -> None:
        self._nav_indicator_after_id = None
        indicator = getattr(self, "_nav_indicator", None)
        target = (
            getattr(self, "all_packages_view_button", None)
            if self._last_scan_all_packages
            else getattr(self, "updates_view_button", None)
        )
        if indicator is None or target is None:
            return
        try:
            if not indicator.winfo_exists() or not target.winfo_exists():
                return
            width = max(self.visuals.px(18), target.winfo_width() - self.visuals.px(12))
            x = target.winfo_x() + (target.winfo_width() - width) // 2
            y = max(0, target.winfo_y() + target.winfo_height() - self.visuals.px(3))
            indicator.place(
                x=x,
                y=y,
                width=width,
                height=self.visuals.px(3),
            )
            indicator.lift()
        except self.tk.TclError:
            return

    def _refresh_scan_view_mode_controls(self) -> None:
        """Make the inventory view visibly read-only instead of merely rejecting clicks."""

        tree = getattr(self, "tree", None)
        columns = getattr(self, "_tree_columns", ())
        if tree is not None and columns:
            displayed = (
                tuple(column for column in columns if column != "selected")
                if self._last_scan_all_packages
                else columns
            )
            with contextlib.suppress(Exception):
                tree.configure(displaycolumns=displayed)
        state = "disabled" if self.busy or self._last_scan_all_packages else "normal"
        for button in self._update_selection_buttons:
            if button is getattr(self, "update_button", None):
                continue
            with contextlib.suppress(Exception):
                button.configure(state=state)
        self._refresh_update_button_readiness()
        self._refresh_secondary_actions_menu()

    def _refresh_secondary_actions_menu(self) -> None:
        menu = getattr(self, "secondary_actions_menu", None)
        entries = getattr(self, "_secondary_action_entries", {})
        if menu is None or not entries:
            return
        raw_holds = self.settings.data.get("attempt_holds", {})
        retry_available = bool(
            isinstance(raw_holds, dict)
            and any(
                item.candidate_key in self._retryable_failure_candidate_keys
                and isinstance((record := raw_holds.get(item.candidate_key)), dict)
                and attempt_hold_classification(record) == CLASS_RETRYABLE
                for item in self._scan_view_items[False].values()
            )
        )
        states = secondary_toolbar_action_states(
            busy=self.busy,
            scan_active=self._scan_active or self._portable_scan_active,
            all_packages=self._last_scan_all_packages,
            retry_available=retry_available,
            report_available=bool(self._scan_view_items[True]),
            cache_clear_inflight=self._cache_clear_inflight,
        )
        for key, index in entries.items():
            with contextlib.suppress(Exception):
                menu.entryconfigure(index, state=states[key])

    def _selected_update_can_run(self) -> bool:
        if self.busy or self._last_scan_all_packages:
            return False
        selected = [item for item in self.items.values() if item.selected]
        if any(self._item_is_bulk_selectable(item) for item in selected):
            return True
        return bool(self._selected_winget_rows_needing_preflight(selected))

    def _refresh_update_button_readiness(self) -> None:
        button = getattr(self, "update_button", None)
        if button is None:
            return
        ready = self._selected_update_can_run()
        review = (
            not ready and not self.busy and not self._last_scan_all_packages
            and any(item.selected and self._item_is_actionable(item) for item in self.items.values())
        )
        ready_border = self.visuals.px(2)
        quiet_border = 0
        quiet_padding = max(0, ready_border - quiet_border)
        if ready or review:
            button.configure(
                text="Review selected" if review else "Update selected",
                state="normal",
                background=self.palette["busy_soft" if review else "update_ready"],
                foreground=self.palette["busy_text" if review else "update_ready_text"],
                activebackground=self.palette["review" if review else "update_ready_active"],
                activeforeground=self.palette["busy_text" if review else "update_ready_text"],
                disabledforeground=self.palette["disabled_text"],
                highlightbackground=self.palette["log_warning" if review else "update_ready_border"],
                highlightcolor=self.palette["log_warning" if review else "update_ready_border"],
                cursor="hand2",
                relief="solid",
                borderwidth=ready_border,
                padx=self.visuals.px(10),
                pady=self.visuals.px(4),
            )
        else:
            button.configure(
                text="Update selected",
                state="disabled",
                background=self.palette["button_disabled"],
                foreground=self.palette["disabled_text"],
                activebackground=self.palette["button_disabled"],
                activeforeground=self.palette["disabled_text"],
                disabledforeground=self.palette["disabled_text"],
                highlightbackground=self.palette["border"],
                highlightcolor=self.palette["border"],
                cursor="arrow",
                relief="flat",
                borderwidth=quiet_border,
                padx=self.visuals.px(10) + quiet_padding,
                pady=self.visuals.px(4) + quiet_padding,
            )

    def _mark_scan_current(self) -> None:
        self._scan_results_current = True
        self._scan_refresh_reason = "Full package-manager scan completed"
        self._refresh_scan_button_style()

    def _mark_scan_refresh_needed(self, reason: str) -> None:
        self._scan_results_current = False
        self._scan_refresh_reason = reason
        self._refresh_scan_button_style()

    def _build_ui(self) -> None:
        tk, ttk = self.tk, self.ttk
        px = self.visuals.px
        self.accent_canvas = tk.Canvas(
            self.root,
            height=px(5),
            highlightthickness=0,
            bd=0,
            background=self.palette["accent"],
        )
        self._register_theme_widget(self.accent_canvas, background="accent")
        self.accent_canvas.pack(fill="x")
        self.accent_canvas.bind("<Configure>", self._schedule_accent_gradient, add="+")
        self.outer = ttk.Frame(
            self.root, padding=(px(18), px(14), px(18), px(14)), style="Surface.TFrame"
        )
        self.outer.pack(fill="both", expand=True)

        self.header_canvas = tk.Canvas(
            self.outer,
            height=px(78),
            highlightthickness=0,
            bd=0,
            background=self.palette["surface"],
        )
        self._register_theme_widget(self.header_canvas, background="surface")
        self.header_canvas.pack(fill="x")
        self.header_canvas.bind("<Button-1>", self._show_header_menu, add="+")
        self.header_title_id = self.header_canvas.create_text(
            px(18),
            px(37),
            anchor="w",
            text="Updates",
            font=self._ui_font(34, semibold=True, display=True),
            fill=self.palette["title"],
            tags=("header_title", "header_content"),
        )
        self.header_canvas.tag_bind("header_title", "<Button-1>", self._show_header_menu, add="+")
        search_box = tk.Frame(
            self.header_canvas,
            background=self.palette["entry_surface"],
            bd=0,
            highlightthickness=0,
        )
        search_label = tk.Label(
            search_box,
            text="Quick search / filter",
            font=self._ui_font(9),
            foreground=self.palette["text_soft"],
            background=self.palette["entry_surface"],
            padx=0,
            pady=0,
        )
        self._register_theme_widget(search_box, background="entry_surface")
        self._register_theme_widget(
            search_label, background="entry_surface", foreground="text_soft"
        )
        search_label.pack(anchor="w")
        search_row = tk.Frame(
            search_box,
            background=self.palette["entry_surface"],
            bd=0,
            highlightthickness=0,
        )
        self._register_theme_widget(search_row, background="entry_surface")
        search_row.pack(anchor="e", pady=(px(3), 0))
        search = ttk.Entry(search_row, textvariable=self.search_var, width=34)
        search.pack(side="left")
        search_clear = tk.Label(
            search_row,
            text="",
            width=2,
            font=self._ui_font(12, semibold=True),
            foreground=self.palette["text_soft"],
            background=self.palette["entry_surface"],
            cursor="arrow",
            padx=0,
            pady=0,
        )
        self._register_theme_widget(
            search_clear,
            background="entry_surface",
            foreground="text_soft",
        )
        search_clear.pack(side="left", fill="y")
        self.header_search_window_id = self.header_canvas.create_window(
            px(8),
            px(10),
            anchor="ne",
            window=search_box,
            tags=("header_content",),
        )
        self.header_canvas.bind("<Configure>", self._schedule_header_gradient, add="+")
        self._bind_widget_tooltip(
            search,
            "Type to filter visible packages by name, ID, version, provider, or status. "
            "Optional exact filters: provider:npm, provider:portable, scope:machine, "
            "is:admin, is:selected (checked), is:held, is:portable. Combine with text; "
            "all conditions must match. Incomplete/unknown filter values match nothing. "
            "Ctrl+F focuses this box; Escape clears it.",
        )
        self._bind_widget_tooltip(search_clear, "Clear the quick search/filter.")
        self.search_entry = search
        self.search_clear_label = search_clear
        search_clear.bind("<Button-1>", self._clear_search_from_button, add="+")
        self.root.bind("<F5>", lambda _event: self.scan())
        self.root.bind("<Control-r>", lambda _event: self.scan())
        self.root.bind("<Control-R>", lambda _event: self.scan())
        self.search_entry.bind("<Escape>", self._clear_search_from_keyboard, add="+")
        self.search_entry.bind("<Control-Return>", self._run_from_keyboard, add="+")
        self.root.bind_all(
            "<Control-f>",
            lambda _event: (
                self.search_entry.focus_set(),
                self.search_entry.select_range(0, "end"),
            ),
        )
        toolbar = ttk.Frame(self.outer)
        toolbar.pack(fill="x", pady=(px(14), px(8)))
        self.scan_button = self._button(
            toolbar,
            text="↻  Scan",
            command=self.scan,
            style="ScanStale.TButton",
            busy_disabled=False,
            tooltip=(
                "Refresh both Updates and All packages from every enabled package manager. "
                "You may rescan during an update batch; each manager waits for its own active "
                "installer, so reads and writes cannot collide. F5 or Ctrl+R does the same. "
                "Dark green means both retained views are current; bold black means a package "
                "or provider change warrants a rescan."
            ),
        )
        self.scan_button.pack(side="left")
        self.updates_view_button = self._button(
            toolbar,
            text="Updates",
            command=lambda: self._show_scan_view(False),
            style="PrimaryNavActive.TButton",
            busy_disabled=False,
            tooltip=(
                "Switch instantly to update candidates. Scans and package operations continue "
                "in the background; filtering remains available."
            ),
        )
        self.updates_view_button.pack(side="left", padx=(px(18), 0))
        self.all_packages_view_button = self._button(
            toolbar,
            text="All packages",
            command=self._activate_all_packages,
            style="PrimaryNav.TButton",
            busy_disabled=False,
            tooltip=(
                "Switch instantly to the installed-package catalog. Scans and package "
                "operations continue in the background; filtering remains available. "
                "Click again to switch between the list and an icon gallery."
            ),
        )
        self.all_packages_view_button.pack(side="left", padx=(px(6), 0))
        self._nav_indicator = tk.Frame(
            toolbar,
            background=self.palette["accent_2"],
            borderwidth=0,
            highlightthickness=0,
        )
        self._register_theme_widget(self._nav_indicator, background="accent_2")
        toolbar.bind(
            "<Configure>",
            lambda _event: self._schedule_nav_indicator(),
            add="+",
        )
        self.scan_portables_button = self._button(
            toolbar,
            text="Scan portables",
            command=self.scan_portables,
            busy_disabled=True,
            tooltip=(
                "Choose a folder to inventory recognized portable apps. Findings persist "
                "in All packages under WinDevPilot · Portables. This release detects "
                "apps, local icons, and PATH visibility but does not update them."
            ),
        )
        self.scan_portables_button.pack(side="left", padx=(px(10), 0))
        self.update_button = tk.Button(
            toolbar,
            text="Update selected",
            command=self.update_selected,
            font=self._ui_font(11, semibold=True),
            padx=px(10),
            pady=px(4),
            borderwidth=px(2),
            highlightthickness=px(1),
            takefocus=True,
        )
        self._bind_widget_tooltip(
            self.update_button,
            "Check the selection, then confirm ordinary updates. For review-only "
            "selections this button explains why nothing can start. Held/problem "
            "updates stay untouched; use sprocket > Test once for a deliberate retry.",
        )
        self._action_buttons.append(self.update_button)
        self._update_selection_buttons.append(self.update_button)
        self.update_button.pack(side="left", padx=(px(24), 0))
        self._refresh_update_button_readiness()
        self.secondary_actions_menu = tk.Menu(
            toolbar,
            tearoff=False,
            postcommand=self._refresh_secondary_actions_menu,
        )
        self._register_theme_widget(
            self.secondary_actions_menu,
            **MENU_THEME_ROLES,
        )
        self._secondary_action_entries.clear()

        def add_secondary_action(key: str, label: str, command: Callable[[], None]) -> None:
            self.secondary_actions_menu.add_command(label=label, command=command)
            self._secondary_action_entries[key] = int(
                self.secondary_actions_menu.index("end")
            )

        add_secondary_action("retry_failed", "Retry failed updates", self.retry_failed_only)
        add_secondary_action("select_recommended", "Select recommended", self.select_recommended)
        add_secondary_action("select_all", "Select all visible", self.select_all)
        add_secondary_action("select_none", "Select none", self.select_none)
        add_secondary_action("test_once", "Test once", self.probe_selected_once)
        self.secondary_actions_menu.add_separator()
        add_secondary_action(
            "save_system_report",
            "Save system report…",
            self.save_system_report,
        )
        add_secondary_action("manage_ignores", "Manage ignores", self.manage_ignores)
        add_secondary_action("holds", "Holds", self.manage_attempt_holds)
        add_secondary_action(
            "clean_graphics_cache",
            "Clean icon and graphics cache…",
            self._clean_graphics_cache_from_ui,
        )
        self.secondary_actions_menu.add_separator()
        add_secondary_action("providers", "Providers", self.configure_providers)
        self._preserve_settings_var = tk.BooleanVar(value=self.settings.data.get("preserve_settings", False))
        self.secondary_actions_menu.add_checkbutton(
            label="Preserve settings", variable=self._preserve_settings_var,
            command=self._toggle_preserve_settings)
        self.secondary_actions_button = ttk.Menubutton(
            toolbar,
            text=SECONDARY_ACTIONS_GLYPH,
            width=3,
            menu=self.secondary_actions_menu,
            style="SecondaryActions.TMenubutton",
            takefocus=True,
        )
        self._bind_widget_tooltip(
            self.secondary_actions_button,
            "More actions: selection helpers, one-time diagnostics, a system report, "
            "ignores, holds, graphics-cache cleaning, and provider settings.",
        )
        self.secondary_actions_button.pack(side="left", padx=(px(8), 0))
        self._button(
            toolbar,
            text="Toolchain health",
            command=self.show_toolchain_health,
            tooltip=(
                "Open a read-only developer toolchain check: detected tool paths, "
                "versions, exit codes, and probe durations. It never updates anything."
            ),
        ).pack(side="right")
        self._button(
            toolbar,
            text="Suggested installs",
            command=self.show_suggested_installs,
            tooltip=(
                "Show curated common Windows developer tools missing from WinGet's "
                "user/machine inventory. Right-click a suggestion to install it through an "
                "available package manager, or copy its exact command."
            ),
        ).pack(side="right", padx=(px(28), px(8)))
        self._refresh_secondary_actions_menu()
        self._refresh_scan_button_style()
        self._schedule_nav_indicator()

        ttk.Label(self.outer, textvariable=self.summary_var, style="Subtitle.TLabel").pack(
            fill="x", pady=(0, px(8))
        )
        self.notification_label = tk.Label(
            self.outer,
            text="",
            anchor="w",
            justify="left",
            padx=px(12),
            pady=px(7),
            background=self.palette["busy_soft"],
            foreground=self.palette["busy_text"],
            font=self._ui_font(10, semibold=True),
            cursor="hand2",
        )
        self.notification_label.bind(
            "<Button-1>", lambda _event: self._hide_notification_banner(), add="+"
        )
        self.activity_label = tk.Label(
            self.outer,
            textvariable=self.activity_var,
            anchor="w",
            padx=px(12),
            pady=px(7),
            background=self.palette["idle"],
            foreground=self.palette["idle_text"],
            font=self._ui_font(10, semibold=True),
        )
        self.activity_label.pack(fill="x", pady=(0, px(8)))
        self.activity_label.bind("<Button-1>", self._activity_strip_click, add="+")
        self._bind_widget_tooltip(
            self.activity_label,
            "Shows whether WinDevPilot is idle, scanning, or running package work. "
            "During a portable scan, click here to stop it.",
        )
        if self.process_is_admin:
            admin_context = tk.Label(
                self.outer,
                text=(
                    "Administrator process: machine-scoped work runs directly; "
                    "user-scoped providers use this account's package homes."
                ),
                anchor="w",
                padx=px(12),
                pady=px(7),
                background=self.palette["surface_alt"],
                foreground=self.palette["text_secondary"],
                font=self._ui_font(10, semibold=True),
            )
            self._register_theme_widget(
                admin_context, background="surface_alt", foreground="text_secondary"
            )
            admin_context.pack(fill="x", pady=(0, px(8)))
            self._bind_widget_tooltip(
                admin_context,
                (
                    "This process already has administrator rights, so eligible machine "
                    "updates do not need a UAC helper. User-scoped package managers still "
                    "use the profile of the account that launched WinDevPilot."
                ),
            )

        self.main_pane = ttk.Panedwindow(self.outer, orient="vertical")
        self.main_pane.pack(fill="both", expand=True)
        tree_frame = ttk.Frame(self.main_pane)
        log_frame = ttk.Frame(self.main_pane)
        self.main_pane.add(tree_frame, weight=4)
        self.main_pane.add(log_frame, weight=1)

        columns = (
            "selected",
            "name",
            "id",
            "current",
            "available",
            "installed_date",
            "provider",
            "status",
        )
        self._tree_columns = columns
        self._package_list_viewport = tk.Frame(tree_frame, background=self.palette["surface"],
                                             borderwidth=0, highlightthickness=0)
        self._register_theme_widget(self._package_list_viewport, background="surface")
        self.tree = ttk.Treeview(self._package_list_viewport, columns=columns, show="tree headings")
        self._tree_headings = {
            "selected": "✓",
            "name": "Package name",
            "id": "Package ID",
            "current": "Installed",
            "available": "Available",
            "installed_date": "Installed / serviced",
            "provider": "Provider",
            "status": "Status",
        }
        self._column_width_dips = {
            "selected": UPDATE_CHECKBOX_COLUMN_WIDTH_DIP,
            "name": 230,
            "id": 250,
            "current": 100,
            "available": 100,
            "installed_date": 105,
            "provider": 105,
            "status": 130,
        }
        self.tree.heading("#0", text="Art", command=self._sort_by_icon_column)
        self.tree.column(
            "#0",
            width=px(PROVIDER_ICON_COLUMN_WIDTH_DIP),
            minwidth=px(PROVIDER_ICON_COLUMN_MIN_WIDTH_DIP),
            stretch=False,
            anchor="center",
        )
        for column in columns:
            self.tree.heading(
                column,
                text=self._tree_headings[column],
                command=lambda selected_column=column: self._sort_by(selected_column),
            )
            self.tree.column(
                column,
                width=px(self._column_width_dips[column]),
                minwidth=(
                    px(UPDATE_CHECKBOX_COLUMN_MIN_WIDTH_DIP) if column == "selected" else px(40)
                ),
                stretch=column in {"name", "id", "status"},
                anchor=(
                    "center"
                    if column in {"selected", "current", "available", "installed_date"}
                    else "w"
                ),
            )
        scrollbar = ttk.Scrollbar(tree_frame, orient="vertical", command=self.tree.yview)
        xscrollbar = ttk.Scrollbar(tree_frame, orient="horizontal", command=self.tree.xview)
        self.tree.configure(
            yscrollcommand=lambda *args: self._tree_yscroll(scrollbar, *args),
            xscrollcommand=xscrollbar.set,
        )
        self.tree.tag_configure("selected", background=self.palette["selected"])
        self.tree.tag_configure("review", background=self.palette["review"])
        self.tree.tag_configure("admin", background=self.palette["admin"])
        self.tree.tag_configure("hover", background=self.palette["hover"])
        self._package_list_viewport.configure(width=self.tree.winfo_reqwidth(), height=self.tree.winfo_reqheight())
        self.tree.place(x=0, y=0, relwidth=1, relheight=1)
        self._package_list_viewport.grid(row=0, column=0, sticky="nsew")
        scrollbar.grid(row=0, column=1, sticky="ns")
        xscrollbar.grid(row=1, column=0, sticky="ew")
        self._package_list_widgets = (self._package_list_viewport, scrollbar, xscrollbar)
        self._build_package_list_drag()
        self._build_package_gallery(tree_frame)
        self.empty_state_label = tk.Label(
            tree_frame,
            text="",
            justify="center",
            background=self.palette["surface"],
            foreground=self.palette["idle_text"],
            font=self._ui_font(14, semibold=True, display=True),
            padx=px(24),
            pady=px(16),
        )
        self._register_theme_widget(
            self.empty_state_label, background="surface", foreground="idle_text"
        )
        self.empty_state_hint_frame = tk.Frame(
            tree_frame,
            background=self.palette["surface"],
            bd=0,
            highlightthickness=0,
        )
        self._register_theme_widget(
            self.empty_state_hint_frame,
            background="surface",
        )
        hint_font = self._ui_font(14, semibold=True, display=True)
        self.empty_state_hint_prefix = tk.Label(
            self.empty_state_hint_frame,
            text="Switch to ",
            background=self.palette["surface"],
            foreground=self.palette["text_soft"],
            font=hint_font,
        )
        self.empty_state_hint_link = tk.Label(
            self.empty_state_hint_frame,
            text="all packages",
            background=self.palette["surface"],
            foreground=self.palette["link"],
            font=hint_font + ("underline",),
            cursor="hand2",
        )
        self.empty_state_hint_suffix = tk.Label(
            self.empty_state_hint_frame,
            text="",
            background=self.palette["surface"],
            foreground=self.palette["text_soft"],
            font=hint_font,
        )
        for hint_widget in (
            self.empty_state_hint_prefix,
            self.empty_state_hint_suffix,
        ):
            self._register_theme_widget(
                hint_widget,
                background="surface",
                foreground="text_soft",
            )
        self._register_theme_widget(
            self.empty_state_hint_link,
            background="surface",
            foreground="link",
        )
        self.empty_state_hint_prefix.pack(side="left")
        self.empty_state_hint_link.pack(side="left")
        self.empty_state_hint_suffix.pack(side="left")
        self.empty_state_hint_link.bind(
            "<Button-1>", lambda _event: self._show_scan_view(True), add="+"
        )
        tree_frame.columnconfigure(0, weight=1)
        tree_frame.rowconfigure(0, weight=1)
        self.tree.bind("<Button-1>", self._tree_click)
        self.tree.bind("<Double-Button-1>", self._tree_double_click)
        self.tree.bind("<Button-3>", self._tree_context_menu)
        self.tree.bind("<Return>", lambda _event: self.show_focused_or_selected_details())
        self.tree.bind("<Control-Return>", self._run_from_keyboard)
        self.tree.bind("<Control-a>", self._tree_select_all_shortcut)
        self.tree.bind("<Control-Button-1>", self._tree_control_click, add="+")
        self.tree.bind("<space>", lambda _event: self._toggle_focused())
        self.tree.bind("<Motion>", self._tree_motion)
        self.tree.bind("<Leave>", self._tree_leave)
        if os.name == "nt":
            self._tree_wheel_rows_per_notch = treeview_wheel_rows_per_notch(
                self.tree.bind_class("Treeview", "<MouseWheel>")
            )
            if self._tree_wheel_rows_per_notch:
                self.tree.bind("<MouseWheel>", self._tree_mousewheel)
        for key_name in ("Up", "Down", "Prior", "Next", "Home", "End"):
            self.tree.bind(f"<KeyPress-{key_name}>", self._tree_scroll_key_pressed, add="+")
            self.tree.bind(f"<KeyRelease-{key_name}>", self._tree_scroll_key_released, add="+")
        self.tree.bind(
            "<Configure>", lambda _event: self._schedule_visible_icon_hydration(), add="+"
        )

        status_bar = ttk.Frame(log_frame)
        status_bar.pack(fill="x", pady=(px(8), px(4)))
        self.progress = ttk.Progressbar(
            status_bar, variable=self.progress_var, maximum=100, mode="determinate"
        )
        self.progress.pack(side="left", fill="x", expand=True)
        # A small activity cue is separate from completed-package progress: a
        # slow first installer must not look idle or imply a measured percentage.
        self._progress_activity = tk.Canvas(
            self.progress, highlightthickness=0, borderwidth=0,
            background=self.palette["progress_trough"],
        )
        self._progress_activity_base = self._progress_activity.create_rectangle(
            0, 0, 1, 1, outline=""
        )
        self._progress_activity_pulse = self._progress_activity.create_rectangle(
            0, 0, 1, 1, outline=""
        )
        self.progress.bind(
            "<Configure>", lambda _event: self._draw_update_progress_activity(), add="+"
        )
        self._bind_widget_tooltip(
            self._progress_activity,
            "Activity only, not a download percentage. The summary distinguishes "
            "checking your request, running an installer, and no update started. "
            "The bar advances as package attempts finish.",
        )
        self.cancel_button = self._button(
            status_bar,
            text="Stop after current",
            command=self.cancel,
            state="disabled",
            tooltip=(
                "Request a graceful stop. The current package process is allowed to "
                "finish; no new package operation will start."
            ),
        )
        self.cancel_button.pack(side="right", padx=(px(8), 0))
        self.bundle_button: Any | None = None
        if self.debug_mode:
            self.bundle_button = self._button(
                status_bar,
                text="Diagnostic bundle",
                command=self.create_diagnostic_bundle_from_ui,
                busy_disabled=True,
                tooltip=(
                    "Create a local zip with the current log, JSONL trace, settings summary, "
                    "visible package evidence, and recent log manifest. The zip path is copied "
                    "to the clipboard for easy sharing with a maintainer or LLM."
                ),
            )
            self.bundle_button.pack(side="right", padx=(px(8), 0))
        self.log_text = tk.Text(
            log_frame,
            height=7,
            wrap="word",
            font=self._mono_font(9),
            relief="solid",
            borderwidth=1,
        )
        self.log_text.pack(fill="both", expand=True)
        self._configure_text_panel(self.log_text, allow_clear=True)
        self._configure_log_tags(self.log_text)
        self.log_text.configure(state="disabled")
        self.main_splitter = tk.Canvas(
            self.main_pane,
            height=px(12),
            borderwidth=0,
            highlightthickness=0,
            cursor="sb_v_double_arrow",
            background=self.palette["header_mid"],
        )
        self.main_splitter.bind("<ButtonPress-1>", self._main_splitter_press, add="+")
        self.main_splitter.bind("<B1-Motion>", self._main_splitter_drag, add="+")
        self.main_splitter.bind("<ButtonRelease-1>", self._main_splitter_release, add="+")
        self.main_splitter.bind("<Configure>", self._draw_main_splitter_gradient, add="+")
        self.main_pane.bind("<Configure>", self._schedule_main_splitter_sync, add="+")
        self._bind_widget_tooltip(
            self.main_splitter,
            "Drag to resize the package list and status output.",
        )
        self._schedule_main_splitter_sync()
        session_base = self.logger.path.with_suffix("")
        self._append_log(
            f"Session files: {session_base} (.log + .jsonl)",
            show_in_ui=False,
        )
        if self.settings.recovered_corrupt_settings is not None:
            self._notify_user(
                "Settings were unreadable and were preserved as "
                f"{self.settings.recovered_corrupt_settings}; defaults are in use.",
                level="warning",
                summary="Recovered from corrupt settings file",
            )

    def _clear_search_from_keyboard(self, _event: Any = None) -> str:
        """Clear an active search without disturbing package state."""
        if self.search_var.get():
            self.search_var.set("")
        self.tree.focus_set()
        return "break"

    def _focus_startup_search(self) -> None:
        """Make ordinary startup typing filter packages until the user chooses another control."""

        if self._closing or not hasattr(self, "search_entry"):
            return
        with contextlib.suppress(self.tk.TclError):
            focused = self.root.focus_get()
            if focused not in (None, self.root):
                return
            self.search_entry.focus_set()
            self.search_entry.icursor("end")

    def _schedule_main_splitter_sync(self, _event: Any = None) -> None:
        if self._closing or not hasattr(self, "main_splitter"):
            return
        self._cancel_after_id("_main_splitter_sync_after_id")
        self._main_splitter_sync_after_id = self.root.after_idle(self._sync_main_splitter)

    def _sync_main_splitter(self) -> None:
        self._main_splitter_sync_after_id = None
        try:
            pane_height = int(self.main_pane.winfo_height())
            pane_width = int(self.main_pane.winfo_width())
            thickness = self.visuals.px(12)
            sash_position = int(self.main_pane.sashpos(0))
            top = max(0, min(pane_height - thickness, sash_position - thickness // 2))
            self.main_splitter.configure(height=thickness)
            self.main_splitter.place(x=0, y=top, width=pane_width, height=thickness)
            # Canvas.lift() raises a drawing item, not the Canvas widget.
            self.main_splitter.tk.call("raise", str(self.main_splitter))
            self._draw_main_splitter_gradient()
        except self.tk.TclError:
            return

    def _main_splitter_press(self, event: Any) -> str:
        try:
            sash_root_y = int(self.main_pane.winfo_rooty()) + int(self.main_pane.sashpos(0))
            self._main_splitter_drag_offset = int(event.y_root) - sash_root_y
        except self.tk.TclError:
            self._main_splitter_drag_offset = 0
        self._hide_tooltip()
        return "break"

    def _main_splitter_drag(self, event: Any) -> str:
        try:
            pane_height = int(self.main_pane.winfo_height())
            requested = (
                int(event.y_root)
                - int(self.main_pane.winfo_rooty())
                - self._main_splitter_drag_offset
            )
            minimum_tree = self.visuals.px(120)
            minimum_log = self.visuals.px(100)
            requested = max(minimum_tree, min(pane_height - minimum_log, requested))
            self.main_pane.sashpos(0, requested)
            self._sync_main_splitter()
        except self.tk.TclError:
            return "break"
        return "break"

    def _main_splitter_release(self, _event: Any = None) -> str:
        self._main_splitter_drag_offset = 0
        self._schedule_main_splitter_sync()
        return "break"

    def _clear_search_from_button(self, _event: Any = None) -> str:
        """Clear the filter while leaving the search box ready for another query."""

        if self.search_var.get():
            self.search_var.set("")
        self.search_entry.focus_set()
        return "break"

    def _on_search_changed(self, *_args: Any) -> None:
        self._note_icon_idle_activity()
        self._update_search_clear_affordance()
        self._schedule_rebuild_tree()

    def _update_search_clear_affordance(self) -> None:
        label = getattr(self, "search_clear_label", None)
        if label is None:
            return
        active = bool(self.search_var.get())
        with contextlib.suppress(self.tk.TclError):
            label.configure(text="×" if active else "", cursor="hand2" if active else "arrow")

    def _fit_main_window(self, geometry: str) -> None:
        fitted, minimum = fit_main_window_geometry(
            geometry, window_monitor_work_area(self.root), self.visuals.px(100) / 100,
        )
        self.root.minsize(*minimum)
        self.root.geometry(fitted)

    def _apply_dpi_metrics(self, _dpi: int) -> None:
        """Reflow explicit pixel metrics when the window changes monitors."""
        if hold := getattr(self, "_resize_hold", None):
            hold.suspend()
        px = self.visuals.px
        source_target = max(48, px(DETAIL_ICON_SIZE_DIP))
        source_target_changed = source_target != self._icon_source_target_px
        if source_target_changed:
            self._icon_source_target_px = source_target
            self._icon_prepare_generation += 1
            getattr(self, "_package_gallery_misses", {}).clear()
            self._package_gallery_attempts.clear()
            self.icon_renderer.set_generation(self._icon_prepare_generation)
            self._icon_resolution_generation += 1
            self._icon_prepare_inflight.clear()
            self._details_icon_callbacks.clear()
            self._item_icon_source_cache.clear()
            self._package_icon_images.clear()
            self._details_icon_images.clear()
            getattr(self, "_compact_icon_images", {}).clear()
            getattr(self, "_compact_icon_tokens", {}).clear()
            getattr(self, "_details_icon_evidence_cache", {}).clear()
            self._package_icon_misses.clear()
            self._package_icon_ready.clear()
            self._reset_ready_icon_memory_load()
            self._reset_background_icon_sweep()
            self._reset_background_details_icon_sweep()
            self._details_background_completed_signature = ""
            self._lazy_icon_batch_active = False
            self._lazy_icon_batch_cached = 0
            self._lazy_icon_batch_failed = 0
            self._lazy_icon_batch_upscaled = 0
        self._fit_main_window(self.root.geometry())
        self.outer.configure(padding=(px(18), px(14), px(18), px(14)))
        self.accent_canvas.configure(height=px(5))
        self.header_canvas.configure(height=px(78))
        self.header_canvas.coords(self.header_title_id, px(18), px(37))
        self.header_canvas.itemconfigure(
            self.header_title_id, font=self._ui_font(34, semibold=True, display=True)
        )
        if hasattr(self, "main_splitter"):
            self.main_splitter.configure(height=px(12))
            self._main_splitter_gradient_key = None
            self._schedule_main_splitter_sync()
        self._draw_accent_gradient()
        self._draw_header_gradient()
        self.style.configure(
            "Treeview",
            rowheight=px(UPDATE_ROW_HEIGHT_DIP),
            font=self._ui_font(10),
        )
        if hasattr(self, "tree"):
            self.tree.column(
                "#0",
                width=px(PROVIDER_ICON_COLUMN_WIDTH_DIP),
                minwidth=px(PROVIDER_ICON_COLUMN_MIN_WIDTH_DIP),
            )
        if hasattr(self, "_provider_icon_images"):
            self._provider_icon_images.clear()
        if hasattr(self, "_tree_icon_kind"):
            self._tree_icon_kind.clear()
        if hasattr(self, "_icon_hydration_after_id"):
            self._schedule_visible_icon_hydration()
        for column, width in self._column_width_dips.items():
            self.tree.column(
                column,
                width=px(width),
                minwidth=(
                    px(UPDATE_CHECKBOX_COLUMN_MIN_WIDTH_DIP) if column == "selected" else px(40)
                ),
            )
        if source_target_changed and self.items:
            self._start_warm_icon_cache_restore()

    @staticmethod
    def _hex_to_rgb(color: str) -> tuple[int, int, int]:
        color = color.lstrip("#")
        return int(color[0:2], 16), int(color[2:4], 16), int(color[4:6], 16)

    @staticmethod
    def _rgb_to_hex(red: int, green: int, blue: int) -> str:
        return f"#{red:02x}{green:02x}{blue:02x}"

    def _gradient_stop_color(
        self, stops: Sequence[tuple[float, tuple[int, int, int]]], ratio: float
    ) -> str:
        ratio = min(1.0, max(0.0, ratio))
        previous_position, previous_color = stops[0]
        for position, color in stops[1:]:
            if ratio <= position:
                span = max(0.001, position - previous_position)
                local = (ratio - previous_position) / span
                return self._rgb_to_hex(
                    int(previous_color[0] + (color[0] - previous_color[0]) * local),
                    int(previous_color[1] + (color[1] - previous_color[1]) * local),
                    int(previous_color[2] + (color[2] - previous_color[2]) * local),
                )
            previous_position, previous_color = position, color
        return self._rgb_to_hex(*stops[-1][1])

    def _draw_gradient_raster(
        self,
        canvas: Any,
        tag: str,
        width: int,
        height: int,
        stops: Sequence[tuple[float, tuple[int, int, int]]],
        *,
        max_bands: int = 128,
    ) -> None:
        """Retain one canvas image; preserve the former bands' exact sampled colors."""
        import tkinter as tk

        state = getattr(canvas, "_wdp_gradient_raster", None)
        if state is None:
            state = {
                "strip": tk.PhotoImage(master=canvas),
                "image": tk.PhotoImage(master=canvas),
                "item": None,
                "strip_key": None,
            }
            canvas._wdp_gradient_raster = state
        band_count = max(1, min(width, max_bands))
        strip_key = (width, band_count, tuple(stops))
        if state["strip_key"] != strip_key:
            # A 1-pixel strip alone does not stretch in Tk. Tile it into the
            # actual canvas-sized raster, including when only height changes.
            row = b"".join(
                bytes.fromhex(self._gradient_stop_color(stops, (index + 0.5) / band_count)[1:])
                * (((index + 1) * width // band_count) - (index * width // band_count))
                for index in range(band_count)
            )
            state["strip"].configure(data=f"P6\n{width} 1\n255\n".encode() + row, format="PPM")
            state["strip_key"] = strip_key
        canvas.tk.call(
            str(state["image"]), "copy", str(state["strip"]),
            "-to", 0, 0, width, height, "-shrink", "-compositingrule", "set",
        )
        if state["item"] is None or not canvas.type(state["item"]):
            state["item"] = canvas.create_image(
                0, 0, image=state["image"], anchor="nw", tags=(tag,),
            )
        canvas.delete(tag + "_overlay")

    def _schedule_header_gradient(self, _event: Any = None) -> None:
        self._cancel_after_id("_header_gradient_after_id")
        self._header_gradient_after_id = self.root.after(48, self._run_scheduled_header_gradient)

    def _run_scheduled_header_gradient(self) -> None:
        self._header_gradient_after_id = None
        self._draw_header_gradient()

    def _schedule_accent_gradient(self, _event: Any = None) -> None:
        self._cancel_after_id("_accent_gradient_after_id")
        self._accent_gradient_after_id = self.root.after(48, self._run_scheduled_accent_gradient)

    def _run_scheduled_accent_gradient(self) -> None:
        self._accent_gradient_after_id = None
        self._draw_accent_gradient()

    def _draw_header_gradient(self, _event: Any = None) -> None:
        canvas = getattr(self, "header_canvas", None)
        if canvas is None:
            return
        width = max(1, int(canvas.winfo_width()))
        height = max(1, int(canvas.winfo_height()))
        stops = (
            (0.0, self._hex_to_rgb(self.palette["header_left"])),
            (0.48, self._hex_to_rgb(self.palette["header_mid"])),
            (1.0, self._hex_to_rgb(self.palette["header_right"])),
        )
        gradient_key = (width, height, stops, self.palette["header_border"])
        if getattr(self, "_header_gradient_key", None) != gradient_key:
            self._header_gradient_key = gradient_key
            self._draw_gradient_raster(canvas, "header_gradient", width, height, stops)
            canvas.create_rectangle(
                0,
                0,
                width - 1,
                height - 1,
                tags=("header_gradient", "header_gradient_overlay"),
                outline=self.palette["header_border"],
                width=1,
            )
            canvas.tag_lower("header_gradient")
        if hasattr(self, "header_search_window_id"):
            canvas.coords(
                self.header_search_window_id, width - self.visuals.px(14), self.visuals.px(13)
            )

    def _draw_main_splitter_gradient(self, _event: Any = None) -> None:
        canvas = getattr(self, "main_splitter", None)
        if canvas is None:
            return
        width = max(1, int(canvas.winfo_width()))
        height = max(1, int(canvas.winfo_height()))
        stops = (
            (0.0, self._hex_to_rgb(self.palette["header_left"])),
            (0.48, self._hex_to_rgb(self.palette["header_mid"])),
            (1.0, self._hex_to_rgb(self.palette["header_right"])),
        )
        gradient_key = (width, height, stops, self.palette["header_border"])
        if getattr(self, "_main_splitter_gradient_key", None) == gradient_key:
            return
        self._main_splitter_gradient_key = gradient_key
        self._draw_gradient_raster(
            canvas,
            "splitter_gradient",
            width,
            height,
            stops,
            max_bands=96,
        )
        canvas.create_rectangle(
            0,
            0,
            width - 1,
            height - 1,
            tags=("splitter_gradient", "splitter_gradient_overlay"),
            outline=self.palette["header_border"],
            width=1,
        )
        center_x = width // 2
        center_y = height // 2
        grip_half_width = max(8, self.visuals.px(10))
        grip_gap = max(2, self.visuals.px(2))
        for offset in (-grip_gap, grip_gap):
            canvas.create_line(
                center_x - grip_half_width,
                center_y + offset,
                center_x + grip_half_width,
                center_y + offset,
                tags=("splitter_gradient", "splitter_gradient_overlay"),
                fill=self.palette["text_soft"],
                width=max(1, self.visuals.px(1)),
            )

    def _show_header_menu(self, event: Any) -> str:
        if getattr(event, "widget", None) is self.search_entry:
            return ""
        menu = self.tk.Menu(self.root, tearoff=False)
        menu.add_command(label=f"About {APP_NAME}", command=self._show_about_window)
        try:
            menu.tk_popup(int(event.x_root), int(event.y_root))
        finally:
            menu.grab_release()
        return "break"

    def _show_about_window(self) -> None:
        ttk = self.ttk
        px = self.visuals.px
        window = self._create_toplevel(self.root)
        window.title(f"About {APP_NAME}")
        window.geometry(self.visuals.geometry_from_dips("460x220"))
        window.transient(self.root)
        frame = ttk.Frame(window, padding=px(18))
        frame.pack(fill="both", expand=True)
        ttk.Label(
            frame,
            text=APP_NAME,
            font=self._ui_font(18, semibold=True, display=True),
        ).pack(anchor="w")
        ttk.Label(
            frame,
            text=f"Version {APP_VERSION}",
            style="Subtitle.TLabel",
        ).pack(anchor="w", pady=(px(4), px(12)))
        body = "Windows developer updater for account-aware package updates."
        ttk.Label(frame, text=body, wraplength=px(390), justify="left").pack(anchor="w", fill="x")
        buttons = ttk.Frame(frame)
        buttons.pack(fill="x", side="bottom", pady=(px(16), 0))
        self._button(
            buttons,
            text="Close",
            command=window.destroy,
            tooltip="Close this About window.",
        ).pack(side="right")

    def _clear_selected_portables_from_list(self, item_keys: Sequence[str]) -> None:
        """Forget selected portable inventory rows without deleting local files."""

        if self.busy or self._portable_scan_active:
            return
        selected_items = [self.items.get(str(key)) for key in item_keys]
        if (
            not selected_items
            or any(item is None for item in selected_items)
            or any(item.provider != PORTABLE_PROVIDER_KEY for item in selected_items if item)
        ):
            return
        executable_keys = {
            _portable_path_key(item.portable_executable)
            for item in selected_items
            if item is not None and item.portable_executable
        }
        if not executable_keys:
            return
        try:
            cached_records_cleared = self.portable_inventory.forget_executables(
                item.portable_executable
                for item in selected_items
                if item is not None and item.portable_executable
            )
        except OSError as exc:
            error = f"{type(exc).__name__}: {exc}"
            self._notify_user(
                f"Selected portables could not be cleared from the list: {error}",
                level="error",
                summary="Selected portables could not be cleared from the list",
            )
            self.logger.event("portable_list_clear_failed", error=error)
            return

        cleared_item_keys: set[str] = set()
        for all_packages in (False, True):
            retained: dict[str, UpdateItem] = {}
            for key, item in self._scan_view_items[all_packages].items():
                if (
                    item.provider == PORTABLE_PROVIDER_KEY
                    and item.portable_executable
                    and _portable_path_key(item.portable_executable) in executable_keys
                ):
                    cleared_item_keys.add(key)
                    continue
                retained[key] = item
            self._scan_view_items[all_packages] = retained
        self._selection_touched_keys.difference_update(cleared_item_keys)
        self._provisional_inventory_keys.difference_update(cleared_item_keys)
        for key in cleared_item_keys:
            self._item_icon_source_cache.pop(key, None)
        self._package_icon_images = {
            memory_key: image
            for memory_key, image in self._package_icon_images.items()
            if memory_key[0] not in cleared_item_keys
        }
        self._package_icon_misses = {
            memory_key
            for memory_key in self._package_icon_misses
            if memory_key[0] not in cleared_item_keys
        }
        self._package_icon_ready = {
            memory_key
            for memory_key in self._package_icon_ready
            if memory_key[0] not in cleared_item_keys
        }
        self.items = self._scan_view_items[self._last_scan_all_packages]
        self._rebuild_tree()
        self._refresh_scan_summary_counts()
        self._update_empty_state()
        visible_count = len(executable_keys)
        noun = "portable" if visible_count == 1 else "portables"
        message = (
            f"Cleared {visible_count} selected {noun} from WinDevPilot's list. "
            "Files and folders were not changed; scan the folder again to restore them."
        )
        self._notify_user(
            message,
            level="success",
            summary=f"Cleared {visible_count} selected {noun} from the list",
        )
        self._append_log(message, show_in_ui=False)
        self.logger.event(
            "portable_list_entries_cleared",
            selected_portables=visible_count,
            cached_records_cleared=cached_records_cleared,
            cleared_item_rows=len(cleared_item_keys),
            files_changed=False,
        )

    def _clean_graphics_cache_from_ui(self) -> None:
        if self._graphics_cache_cleaning_blocked():
            return
        if not self.messagebox.askokcancel(
            "Clean icon and graphics cache?",
            "Delete WinDevPilot's cached icons and generated graphics?\n\n"
            "They will be recreated as needed; icons may take a moment to reappear.\n\n"
            "Installation-date metadata will not be deleted. Package and portable "
            "inventories, installation/update history, settings, and logs will be kept.\n\n"
            "Installed applications and their original artwork will not be changed.",
            parent=self.root,
            default="cancel",
            icon="warning",
        ):
            return
        self._clear_graphics_cache()

    def _graphics_cache_cleaning_blocked(self) -> bool:
        return bool(
            self._closing or self.busy or self._scan_active or self._portable_scan_active
            or self._cache_clear_inflight
        )

    def _clear_graphics_cache(self) -> None:
        # Recheck after the modal dialog: Tk can deliver background events there.
        if self._graphics_cache_cleaning_blocked():
            return
        self._cache_clear_inflight = True
        self._schedule_icon_sort_refresh()
        self._icon_resolution_generation += 1
        self._icon_sort_colors.clear()
        self._refresh_secondary_actions_menu()
        invalidate_start_menu_shortcut_index()
        self._icon_prepare_generation += 1
        getattr(self, "_package_gallery_misses", {}).clear()
        self._package_gallery_attempts.clear()
        self.icon_renderer.set_generation(self._icon_prepare_generation)
        self._warm_icon_restore_generation += 1
        self._icon_catalog_load_generation += 1
        self._icon_catalog_write_generation += 1
        self._icon_catalog_write_active = False
        self._icon_catalog_write_pending = False
        self._cancel_after_id("_icon_catalog_write_after_id")
        self._icon_catalog_entries.clear()
        self._icon_catalog_blobs.clear()
        self._cancel_after_id("_details_idle_after_id")
        if hasattr(self, "_details_idle_queue"):
            self._details_idle_queue.clear()
            self._details_idle_vector_paths.clear()
        self._icon_catalog_valid_paths.clear()
        self._icon_catalog_list_display_paths.clear()
        # The prior load was superseded above; our intentional empty baseline
        # is ready for checkpoints once cache cleaning finishes.
        self._icon_catalog_loaded = True
        self._icon_catalog_decode_queue.clear()
        self._cancel_after_id("_icon_catalog_decode_after_id")
        self._provider_icon_images.clear()
        self._package_icon_images.clear()
        self._details_icon_images.clear()
        getattr(self, "_compact_icon_images", {}).clear()
        getattr(self, "_compact_icon_tokens", {}).clear()
        getattr(self, "_details_icon_evidence_cache", {}).clear()
        self._package_icon_misses.clear()
        self._package_icon_ready.clear()
        self._reset_ready_icon_memory_load()
        self._reset_background_icon_sweep()
        self._reset_background_details_icon_sweep()
        self._details_background_completed_signature = ""
        self._item_icon_source_cache.clear()
        self._tree_icon_kind.clear()
        self._icon_prepare_inflight.clear()
        self._details_icon_callbacks.clear()
        self._cancel_after_id("_icon_gallery_photo_decode_after_id")
        self._icon_gallery_photo_decode_queue.clear()
        self._icon_gallery_photo_decode_pending.clear()
        self._icon_gallery_blit_cache.clear()
        for key in tuple(getattr(self, "_icon_gallery_preparations", {})):
            self._discard_icon_gallery_preparation(key)
        getattr(self, "_icon_gallery_queued_jobs", {}).clear()
        pending_galleries = list(getattr(self, "_icon_gallery_inflight", {}).values())
        getattr(self, "_icon_gallery_inflight", {}).clear()
        for callbacks in pending_galleries:
            for callback in callbacks:
                with contextlib.suppress(self.tk.TclError):
                    callback(IconGalleryMemoryBundle(b"", 0), "Graphics cache cleared; reopen Icon Lineup.")
        self._icon_showcase_cache.clear()
        self._icon_showcase_inflight.clear()
        self._icon_gallery_blit_bytes = 0
        self._icon_gallery_blit_report_threshold = ICON_GALLERY_BLIT_MEMORY_REPORT_START
        self._icon_gallery_blit_warmup_announced = False
        self._lazy_icon_batch_active = False
        self._cancel_after_id("_icon_key_release_after_id")
        self._cancel_after_id("_icon_batch_finish_after_id")
        for row in self.tree.get_children():
            item = self.items.get(str(row))
            if item is None:
                continue
            with contextlib.suppress(Exception):
                image = self._fallback_icon(item)
                getattr(self, "_tree_row_presentations", {}).pop(row, None)
                self.tree.item(row, image=image, text="")
                self._tree_icon_kind[str(row)] = "provider"
        self._append_log("Cleaning icon and graphics cache; installation-date metadata is kept…")

        def worker() -> None:
            # Generation invalidation terminates the renderer first. Waiting off
            # Tk's thread prevents an in-flight child from resurrecting a cache
            # file after the sweep has completed.
            if not self.icon_renderer.wait_idle(timeout=5.0):
                raise RuntimeError("Icon renderer is still busy; cached files were not deleted")
            # Serialize against the atomic catalog writer so a writer that
            # already passed its generation check cannot resurrect the index.
            with self._icon_catalog_write_lock:
                removed, retained = clear_generated_icon_cache_files()
                _load_vector_bitmap.cache_clear()
                _vector_icon_png.cache_clear()
                _v64_ramp.cache_clear()
            self.events.put(("caches_cleared", (removed, retained)))

        self._start_guarded_worker(
            worker,
            name="wdp-cache-clear",
            operation="cache-clear",
        )

    def _finish_cache_clear(self, removed: int, retained: int = 0) -> None:
        self._cache_clear_inflight = False
        self._schedule_package_gallery_render()
        self._refresh_secondary_actions_menu()
        self._schedule_visible_icon_hydration()
        self._schedule_background_icon_sweep(restart=True, delay_ms=120)
        self._notify_user(
            f"Graphics cache cleaned: {removed} generated file(s) cleared. "
            + (f"{retained} other or inaccessible entries left unchanged. " if retained else "")
            + "Installation-date metadata was preserved.",
            level="warning" if retained else "success",
            summary="Graphics cache cleaned",
        )

    def _draw_accent_gradient(self, _event: Any = None) -> None:
        canvas = getattr(self, "accent_canvas", None)
        if canvas is None:
            return
        width = max(1, int(canvas.winfo_width()))
        height = max(1, int(canvas.winfo_height()))
        if self.busy:
            left = self._hex_to_rgb(self.palette["busy"])
            right = self._hex_to_rgb(self.palette["busy_2"])
        else:
            left = self._hex_to_rgb(self.palette["accent"])
            right = self._hex_to_rgb(self.palette["accent_2"])
        stops = ((0.0, left), (1.0, right))
        gradient_key = (width, height, stops)
        if getattr(self, "_accent_gradient_key", None) != gradient_key:
            self._accent_gradient_key = gradient_key
            self._draw_gradient_raster(canvas, "accent_gradient", width, height, stops, max_bands=96)
            canvas.tag_lower("accent_gradient")
        pulse_ids = getattr(self, "_accent_pulse_ids", [])
        if len(pulse_ids) != 5:
            pulse_ids = [
                canvas.create_rectangle(0, 0, 0, 0, outline="", state="hidden")
                for _index in range(5)
            ]
            self._accent_pulse_ids = pulse_ids
        if not self.busy or not self._client_animations_enabled:
            for pulse_id in pulse_ids:
                canvas.itemconfigure(pulse_id, state="hidden")
            return
        band_width = max(60, width // 6)
        start = (self._busy_pulse_offset % (width + band_width)) - band_width
        highlight = self._hex_to_rgb(self.palette["busy_pulse"])
        strengths = (0.10, 0.24, 0.42, 0.24, 0.10)
        for index, (pulse_id, strength) in enumerate(zip(pulse_ids, strengths, strict=True)):
            band_left = start + index * band_width / len(pulse_ids)
            band_right = start + (index + 1) * band_width / len(pulse_ids)
            center_ratio = min(1.0, max(0.0, ((band_left + band_right) / 2) / width))
            base = tuple(
                int(left[channel] + (right[channel] - left[channel]) * center_ratio)
                for channel in range(3)
            )
            color = self._rgb_to_hex(
                *(
                    int(base[channel] + (highlight[channel] - base[channel]) * strength)
                    for channel in range(3)
                )
            )
            canvas.coords(pulse_id, band_left, 0, band_right + 1, height)
            canvas.itemconfigure(pulse_id, fill=color, state="normal")

    def _report_visual_diagnostics(self) -> None:
        diagnostics = self.visuals.diagnostics()
        diagnostics["theme_mode"] = self.palette["mode"]
        if hold := getattr(self, "_resize_hold", None):
            diagnostics["resize_hold_attached"] = bool(hold._hwnd)
            diagnostics["resize_hold_error"] = hold.error
        self.logger.event("windows_visuals", **diagnostics)

    def _append_log(
        self,
        message: str,
        *,
        already_redacted: bool = False,
        show_in_ui: bool = True,
        persist: bool = True,
    ) -> None:
        """Persist diagnostic evidence, optionally omitting mechanical detail from the GUI."""

        safe_message = str(message) if already_redacted else redact_sensitive_text(message)
        if persist:
            self.logger.write(safe_message, already_redacted=True)
        if not show_in_ui:
            return
        pending = getattr(self, "_ui_log_batch", None)
        if pending is not None:
            pending.append(safe_message)
            return
        self._paint_log_messages((safe_message,))

    def _paint_log_messages(self, messages: Sequence[str]) -> None:
        """Queue presentation only; durable logging has already retained each message."""

        pending = getattr(self, "_pending_log_lines", None)
        if pending is None:
            pending = self._pending_log_lines = deque()
        pending.extend(iter(message.splitlines() or [""]) for message in messages)
        if getattr(self, "_log_paint_after_id", None) is None:
            self._drain_log_paint()

    def _drain_log_paint(self) -> None:
        self._log_paint_after_id = None
        if getattr(self, "_closing", False):
            self._pending_log_lines.clear()
            return
        if self._native_window_interaction_active():
            self._log_paint_after_id = self.root.after(40, self._drain_log_paint)
            return
        deadline = time.perf_counter() + 0.003
        count = characters = 0
        # Include actual Text insertion/layout work in the presentation budget.
        while self._pending_log_lines and count < 80 and characters < 16_000:
            line = next(self._pending_log_lines[0], None)
            if line is None:
                self._pending_log_lines.popleft()
                continue
            self._paint_log_lines((line,))
            count += 1
            characters += min(len(line), MAX_LOG_LINE_CHARS)
            if time.perf_counter() >= deadline:
                break
        if self._pending_log_lines:
            self._log_paint_after_id = self.root.after(4, self._drain_log_paint)

    def _paint_log_lines(self, messages: Sequence[str]) -> None:
        """Insert a bounded unit, following output only for readers already at the end."""

        if not messages:
            return
        follow = self.log_text.yview()[1] >= 0.999
        self.log_text.configure(state="normal")
        for message in messages:
            for line in message.splitlines() or [""]:
                if len(line) > MAX_LOG_LINE_CHARS:
                    omitted = len(line) - MAX_LOG_LINE_CHARS
                    line = f"{line[:MAX_LOG_LINE_CHARS]} … [{omitted} chars hidden in UI]"
                tag = self._log_visual_tag(line)
                marker = self._log_visual_marker(tag)
                if marker:
                    self.log_text.insert("end", marker, (tag,))
                text_tags = ("log_dim",) if tag == "log_dim" else ()
                self.log_text.insert("end", line.rstrip() + "\n", text_tags)
        line_count = int(self.log_text.index("end-1c").split(".", maxsplit=1)[0])
        if line_count > MAX_LOG_WIDGET_LINES:
            self.log_text.delete("1.0", f"{line_count - MAX_LOG_WIDGET_LINES}.0")
        if follow:
            self.log_text.see("end")
        self.log_text.configure(state="disabled")

    def _notify_user(
        self, message: str, *, level: str = "info", summary: str | None = None
    ) -> None:
        """Report routine user-facing feedback in-window, not with modal popups."""
        prefixes = {"success": "Success", "warning": "Warning", "error": "Error", "info": "Info"}
        label = prefixes.get(level, "Info")
        clean_message = " ".join(message.split())
        summary_message = summary or clean_message
        self.summary_var.set(summary_message)
        self._append_log(f"{label}: {message}")
        # Advisory warnings already have a stable summary line and detailed log.
        # Expanding the layout for them is distracting; reserve the banner for
        # failures that genuinely require attention.
        if level == "error":
            self._show_notification_banner(summary_message, level=level)

    def _show_notification_banner(self, message: str, *, level: str) -> None:
        """Show one compact, non-modal attention banner without obscuring activity state."""
        if self._closing or not hasattr(self, "notification_label"):
            return
        self._hide_notification_banner()
        is_error = level == "error"
        self._notification_level = level
        prefix = "✕" if is_error else "⚠"
        compact = " ".join(message.split())
        if len(compact) > 240:
            compact = f"{compact[:237].rstrip()}…"
        self.notification_label.configure(
            text=f"{prefix}  {compact}    (click to dismiss)",
            background=self.palette["danger_surface" if is_error else "busy_soft"],
            foreground=self.palette["danger_text" if is_error else "busy_text"],
        )
        self.notification_label.pack(
            fill="x",
            pady=(0, self.visuals.px(8)),
            before=self.activity_label,
        )
        self._notification_after_id = self.root.after(
            NOTIFICATION_ERROR_MS if is_error else NOTIFICATION_WARNING_MS,
            self._hide_notification_banner,
        )

    def _hide_notification_banner(self) -> None:
        self._cancel_after_id("_notification_after_id")
        if hasattr(self, "notification_label"):
            self.notification_label.pack_forget()

    def _native_window_interaction_active(self) -> bool:
        """Return whether Windows is currently moving or sizing the main window."""

        resize_hold = getattr(self, "_resize_hold", None)
        return bool(resize_hold is not None and resize_hold._in_loop)

    def _set_progress_value(self, target: float, *, animate: bool = True) -> None:
        """Move determinate progress smoothly; never delay or drive package work."""
        self._cancel_after_id("_progress_after_id")
        target = min(100.0, max(0.0, float(target)))
        try:
            start_value = float(self.progress_var.get())
        except (TypeError, ValueError):
            start_value = target
        if not animate or target <= start_value or abs(target - start_value) < 0.25:
            self.progress_var.set(target)
            self._draw_update_progress_activity()
            return
        started = time.perf_counter()

        def tick() -> None:
            if self._native_window_interaction_active():
                self._progress_after_id = self.root.after(
                    WINDOW_DRAG_BUSY_ANIMATION_POLL_MS, tick
                )
                return
            elapsed = time.perf_counter() - started
            fraction = min(1.0, elapsed / PROGRESS_TWEEN_SECONDS)
            eased = 1.0 - (1.0 - fraction) ** 3
            self.progress_var.set(start_value + (target - start_value) * eased)
            self._draw_update_progress_activity()
            if fraction >= 1.0 or self._closing:
                self._progress_after_id = None
                return
            self._progress_after_id = self.root.after(PROGRESS_TWEEN_INTERVAL_MS, tick)

        tick()

    def _draw_update_progress_activity(self) -> None:
        """Paint only the zero-completion cue, reusing the existing busy timer."""
        canvas = getattr(self, "_progress_activity", None)
        if canvas is None:
            return
        checking_or_updating = self.busy and self._busy_kind in {"selected-preflight", "update"}
        brief_acknowledgment = (
            not self.busy and not getattr(self, "_scan_active", False)
            and time.monotonic() < getattr(self, "_update_request_cue_until", 0.0)
        )
        if not ((checking_or_updating or brief_acknowledgment) and float(self.progress_var.get()) == 0.0):
            if canvas.winfo_manager():
                canvas.place_forget()
            return
        width = min(self.visuals.px(64), max(1, self.progress.winfo_width() - 4))
        height = max(1, self.progress.winfo_height() - 4)
        canvas.place(x=2, y=2, width=width, height=height)
        trough = self.palette["progress_trough"]
        green = self.palette["progress"]
        canvas.configure(background=trough)
        base_width = min(width, self.visuals.px(18))
        canvas.coords(self._progress_activity_base, 0, 0, base_width, height)
        canvas.itemconfigure(self._progress_activity_base, fill=green)
        # Travel away from the solid marker and blend into the trough. Respect
        # reduced-motion preferences and the existing native-gesture pause.
        phase = (time.monotonic() % 1.4) / 1.4 if self._client_animations_enabled else 0.0
        pulse_width = self.visuals.px(9)
        x = base_width + phase * max(0, width - base_width)
        start_rgb = tuple(round(c + (255 - c) * 0.5) for c in self._hex_to_rgb(green))
        end_rgb = self._hex_to_rgb(trough)
        color = self._rgb_to_hex(*(
            round(a + (b - a) * phase) for a, b in zip(start_rgb, end_rgb)
        ))
        canvas.coords(self._progress_activity_pulse, x, 0, min(width, x + pulse_width), height)
        canvas.itemconfigure(self._progress_activity_pulse, fill=color)

    @staticmethod
    def _log_visual_tag(line: str) -> str:
        folded = line.casefold()
        if folded.startswith("success:"):
            return "log_success"
        if folded.startswith("warning:"):
            return "log_warning"
        if folded.startswith("update run finished:"):
            if re.search(r"\b[1-9]\d* failed\b|\b[1-9]\d* cancelled\b", folded):
                return "log_failure"
            if re.search(
                r"\b[1-9]\d* not applicable\b|"
                r"\b[1-9]\d* with warnings\b|"
                r"\b[1-9]\d* need restart\b",
                folded,
            ):
                return "log_warning"
            if re.search(r"\b[1-9]\d* updated\b|\b[1-9]\d* already current\b", folded):
                return "log_success"
            return "log_info"
        if folded.startswith("attempted-package refresh"):
            def count(label: str) -> int:
                match = re.search(rf"\b(\d+) {re.escape(label)}\b", folded)
                return int(match.group(1)) if match else 0

            if (
                count("still offered")
                or count("awaiting restart")
                or count("unverified")
            ):
                return "log_warning"
            if count("no longer offered"):
                return "log_success"
            return "log_info"
        if folded.startswith("verification finished:"):
            def count(label: str) -> int:
                match = re.search(rf"\b(\d+) {re.escape(label)}\b", folded)
                return int(match.group(1)) if match else 0

            if count("still offered") or count("awaiting restart") or count("unverified"):
                return "log_warning"
            if count("no longer offered"):
                return "log_success"
            return "log_info"
        if (
            "failed" in folded
            or "could not" in folded
            or "error" in folded
            or "timed_out=true" in folded
            or "cancelled" in folded
        ):
            return "log_failure"
        if (
            "updated with warnings" in folded
            or "dependency warnings" in folded
            or "warning:" in folded
            or " warning:" in folded
            or "not applicable" in folded
            or "guidance:" in folded
            or "still offered" in folded
            or "need restart" in folded
            or "restart required" in folded
        ):
            return "log_warning"
        if (
            ": updated" in folded
            or " updated," in folded
            or " updated •" in folded
            or "updated and" in folded
            or "already current" in folded
            or "no longer offered" in folded
            or "diagnostic bundle created" in folded
        ):
            return "log_success"
        if (
            folded.startswith("session files:")
            or folded.startswith("scanning for updates")
            or folded.startswith("listing installed packages")
            or folded.startswith("scan complete:")
        ):
            return "log_info"
        if folded.startswith("command:") or folded.startswith("process:"):
            return "log_dim"
        return ""

    @staticmethod
    def _log_visual_marker(tag: str) -> str:
        return {
            "log_success": "■ ",
            "log_warning": "■ ",
            "log_failure": "■ ",
            "log_info": "◆ ",
        }.get(tag, "")

    def _set_busy(self, value: bool, activity: str | None = None, *, kind: str = "") -> None:
        if not value and self._scan_active:
            value = True
            kind = "scan"
            activity = "Refreshing updates and installed packages"
            self._active_scan_owns_busy = True
        self.busy = value
        self._busy_kind = kind if value else ""
        state = "disabled" if value or self._scan_active else "normal"
        for button in self._action_buttons:
            with contextlib.suppress(Exception):
                button.configure(state=state)
        if self._diagnostic_bundle_inflight and self.bundle_button is not None:
            self.bundle_button.configure(state="disabled")
        self._refresh_scan_view_mode_controls()
        self.cancel_button.configure(
            state="normal" if value or self._scan_active else "disabled",
            text=(
                "Stop checks"
                if value and kind == "selected-preflight"
                else "Stop scan"
                if (value and kind in {"scan", "portable-scan"})
                or (not value and self._scan_active)
                else "Stop after current"
            ),
        )
        self.activity_label.configure(cursor="hand2" if value and kind == "portable-scan" else "")
        self._refresh_scan_button_style()
        if value:
            self._start_activity(activity or "Working")
        else:
            self._stop_activity()
        self._draw_update_progress_activity()
        self._update_empty_state()

    def _activity_strip_click(self, event: Any) -> str | None:
        if not self.busy or self._busy_kind != "portable-scan":
            return None
        menu = self.tk.Menu(self.activity_label, tearoff=False)
        menu.add_command(
            label="Stop portable scan",
            command=self.cancel,
            state="disabled" if self.cancel_requested.is_set() else "normal",
        )
        menu.tk_popup(event.x_root, event.y_root)
        menu.grab_release()
        return "break"

    def _start_activity(self, activity: str) -> None:
        self._activity_base = activity
        self._activity_spinner_index = 0
        self._busy_pulse_offset = 0
        self.root.title(f"{APP_NAME} {APP_VERSION} - BUSY")
        self.activity_label.configure(
            background=self.palette["busy_soft"], foreground=self.palette["busy_text"]
        )
        self.accent_canvas.configure(height=self.visuals.px(8))
        if self._activity_after_id is None:
            self._animate_activity()

    def _stop_activity(self) -> None:
        self._cancel_after_id("_activity_after_id")
        self._activity_base = "Idle - no package operation is running"
        self.activity_var.set(f"✓ {self._activity_base}")
        self.root.title(f"{APP_NAME} {APP_VERSION}")
        self.activity_label.configure(
            background=self.palette["idle"], foreground=self.palette["idle_text"]
        )
        self.accent_canvas.configure(height=self.visuals.px(5))
        self._draw_accent_gradient()

    def _animate_activity(self) -> None:
        if not self.busy:
            self._activity_after_id = None
            return
        if self._native_window_interaction_active():
            # Moving or sizing the native window is an exclusive gesture. Leave
            # the decorative busy strip at its last frame until the gesture ends.
            self._activity_after_id = self.root.after(
                WINDOW_DRAG_BUSY_ANIMATION_POLL_MS, self._animate_activity
            )
            return
        if self._client_animations_enabled:
            frames = ("●○○", "○●○", "○○●", "○●○")
            frame = frames[(self._activity_spinner_index // 2) % len(frames)]
            self._activity_spinner_index += 1
            self._busy_pulse_offset += max(5, self.visuals.px(7))
            delay_ms = 70
        else:
            frame = "●"
            delay_ms = 500
        self.activity_var.set(f"{frame} {self._activity_base} - operation in progress")
        self._draw_accent_gradient()
        self._draw_update_progress_activity()
        self._activity_after_id = self.root.after(delay_ms, self._animate_activity)

    def _set_header_title(self, title: str) -> None:
        if hasattr(self, "header_canvas") and hasattr(self, "header_title_id"):
            with contextlib.suppress(Exception):
                self.header_canvas.itemconfigure(self.header_title_id, text=title)

    def scan(self) -> None:
        self._start_scan(origin="manual")

    def retry_failed_only(self) -> None:
        """Release only latest-run retryable holds, then rescan and select safely."""

        if self.busy or self._scan_active:
            return
        raw_holds = self.settings.data.get("attempt_holds", {})
        if not isinstance(raw_holds, dict):
            return
        candidate_keys = {
            item.candidate_key
            for item in self._scan_view_items[False].values()
            if item.candidate_key in self._retryable_failure_candidate_keys
            and isinstance((record := raw_holds.get(item.candidate_key)), dict)
            and attempt_hold_classification(record) == CLASS_RETRYABLE
        }
        if not candidate_keys:
            self._notify_user(
                "No retryable failures from the latest run remain in the current scan.",
                summary="No retryable failures are available",
            )
            self._refresh_secondary_actions_menu()
            return
        previous_failures = retryable_failure_context(self.settings.data, candidate_keys)
        if not self.messagebox.askokcancel(
            "Retry failed packages",
            (
                f"Release the retry safety hold for {len(candidate_keys)} exact package "
                "candidate(s), then run a read-only scan?\n\n"
                f"{previous_failures}\n\n"
                "Candidates that are still ordinary updates will be selected, but no "
                "update will start. Fix the reported busy process, restart, or network "
                "condition before clicking Update selected."
            ),
            parent=self.root,
        ):
            return
        original_holds = self.settings.data.get("attempt_holds")
        original_history = self.settings.data.get("applicability_history")
        released = release_attempt_holds(self.settings.data, candidate_keys, self.logger)
        try:
            self.settings.save()
        except OSError as exc:
            self.settings.data["attempt_holds"] = original_holds
            self.settings.data["applicability_history"] = original_history
            self._notify_user(
                f"Could not save the released retry holds: {exc}",
                level="error",
                summary="Retry holds were not changed",
            )
            return
        self._pending_retry_selection_candidate_keys = set(candidate_keys)
        self._retryable_failure_candidate_keys.clear()
        if self._last_scan_all_packages:
            self._show_scan_view(False)
        self._append_log(
            f"Released {released} retryable hold(s); rescanning before selecting candidates"
        )
        self.logger.event(
            "retry_failed_rescan_requested",
            released_count=released,
            candidate_keys=sorted(candidate_keys),
            automatic_update_started=False,
        )
        self.scan()

    def scan_portables(self) -> None:
        if self.busy or self._portable_scan_active:
            self._append_log("Portable scan was not started because another operation is active")
            return
        roots = self.portable_inventory.roots()
        initial_directory = roots[-1] if roots and Path(roots[-1]).is_dir() else str(Path.home())
        selected = self.filedialog.askdirectory(
            parent=self.root,
            title="Choose a folder containing portable apps",
            initialdir=initial_directory,
            mustexist=True,
        )
        if not selected:
            return
        if rejection := portable_scan_root_rejection(selected):
            self.summary_var.set("Choose a non-system folder containing portable apps")
            self._append_log(f"Portable scan skipped: {rejection}")
            self.logger.event(
                "portable_scan_root_rejected",
                root=selected,
                reason=rejection,
            )
            return
        self.cancel_requested.clear()
        self._portable_scan_active = True
        self._set_busy(
            True,
            f"Scanning {Path(selected).name or selected} for portable apps",
            kind="portable-scan",
        )
        self.progress.configure(mode="indeterminate")
        self.progress.start(INDETERMINATE_PROGRESS_INTERVAL_MS)
        self.summary_var.set("Scanning the selected folder for recognized portable apps…")
        self._append_log(f"Portable scan started: {selected}")
        self.logger.event("portable_scan_requested", root=selected)

        def worker() -> None:
            try:
                result = scan_portable_root(
                    selected,
                    self.cancel_requested,
                    lambda progress: self.events.put(
                        ("portable_scan_progress", progress)
                    ),
                )
                if self.cancel_requested.is_set() and not result.cancelled:
                    result = dataclasses.replace(result, cancelled=True)
                if not result.cancelled:
                    self.portable_inventory.replace_root(result)
                error = ""
            except Exception as exc:
                result = None
                error = f"{type(exc).__name__}: {exc}"
            self.events.put(("portable_scan_done", (result, error)))

        self._start_guarded_worker(
            worker,
            name="wdp-portable-scan",
            operation="portable-scan",
        )

    def _show_portable_scan_progress(self, progress: PortableScanProgress) -> None:
        if not self._portable_scan_active or self._closing:
            return
        app_label = "app" if progress.apps_found == 1 else "apps"
        elapsed = int(progress.elapsed_seconds)
        message = (
            f"Portable scan still working: {progress.apps_found} high-confidence "
            f"portable {app_label} found so far; "
            f"{progress.files_checked} executable(s) checked in {elapsed}s"
        )
        self.summary_var.set(message)
        self._append_log(message)
        self.logger.event(
            "portable_scan_progress",
            root=progress.root,
            apps_found=progress.apps_found,
            files_checked=progress.files_checked,
            directories_checked=progress.directories_checked,
            elapsed_seconds=round(progress.elapsed_seconds, 1),
        )

    def _merge_portable_records(
        self,
        records: Sequence[PortableRecord],
    ) -> tuple[list[UpdateItem], list[UpdateItem]]:
        """Replace portable rows in both views from one verified record snapshot."""

        portable_items = [portable_record_to_item(record) for record in records]
        portable_updates = apply_stored_selection_policy(
            [
                advisory
                for record in records
                if (advisory := portable_record_to_update_item(record)) is not None
            ],
            self.settings.data,
        )
        for all_packages, additions in (
            (True, portable_items),
            (False, portable_updates),
        ):
            merged = {
                key: item
                for key, item in self._scan_view_items[all_packages].items()
                if item.provider != PORTABLE_PROVIDER_KEY
            }
            merged.update({item.key: item for item in additions})
            self._scan_view_items[all_packages] = merged
        return portable_items, portable_updates

    def _start_portable_cache_verification(self) -> None:
        if self._portable_cache_verification_active or self._closing:
            return
        self._portable_cache_verification_active = True
        cached_count = len(self.portable_inventory.records())
        if cached_count:
            self._append_log(
                f"Verifying {cached_count} cached portable app(s) and saved folder(s)…"
            )

        def worker() -> None:
            try:
                result = self.portable_inventory.verify_records()
                error = ""
            except Exception as exc:
                result = PortableInventoryVerification(())
                error = f"{type(exc).__name__}: {exc}"
            self.events.put(("portable_cache_verified", (result, error)))

        threading.Thread(
            target=worker,
            name="wdp-portable-cache-verify",
            daemon=True,
        ).start()

    def _finish_portable_cache_verification(
        self,
        result: PortableInventoryVerification,
        error: str,
    ) -> None:
        self._portable_cache_verification_active = False
        if self._closing:
            return
        if error:
            self.logger.event("portable_cache_verification_failed", error=error)
            return
        portable_items, _portable_updates = self._merge_portable_records(result.records)
        if not self.busy:
            self.items = self._scan_view_items[self._last_scan_all_packages]
            self._rebuild_tree()
            self._refresh_scan_summary_counts()
        verification_parts = [f"{len(portable_items)} cached app(s) available"]
        if result.pruned_records:
            verification_parts.append(f"{result.pruned_records} missing app(s) removed")
        if result.unreachable_roots:
            verification_parts.append(
                f"{len(result.unreachable_roots)} unavailable root(s) temporarily hidden"
            )
        if portable_items or result.pruned_records or result.unreachable_roots:
            self._append_log("Portable cache verified: " + "; ".join(verification_parts))
        self.logger.event(
            "portable_cache_verified",
            cached_items=len(portable_items),
            pruned_records=result.pruned_records,
            unreachable_roots=list(result.unreachable_roots),
        )
        self._request_portable_local_refresh()

    def _request_portable_local_refresh(self) -> None:
        """Run one low-priority local-version confirmation after the main scan."""

        if self._closing or self._portable_local_refresh_completed:
            return
        if (
            self._last_scan_completed_at is None
            or self._portable_cache_verification_active
            or self._portable_scan_active
            or self._portable_catalog_refresh_active
            or self._portable_local_refresh_active
        ):
            self._portable_local_refresh_pending = True
            return
        records, revision = self.portable_inventory.catalog_snapshot()
        self._portable_local_refresh_pending = False
        if not records:
            self._portable_local_refresh_completed = True
            self._start_portable_catalog_refresh()
            if not self._icon_background_sweep_active:
                self._start_background_details_icon_sweep()
            return
        self._portable_local_refresh_active = True
        self._append_log(f"Confirming local versions for {len(records)} portable app(s)…")
        self.logger.event(
            "portable_local_version_refresh_started",
            cached_records=len(records),
        )

        def worker() -> None:
            try:
                result = refresh_portable_local_records(records)
                changed = self.portable_inventory.update_local_records(
                    result.records,
                    expected_revision=revision,
                )
                error = ""
            except Exception as exc:
                result = PortableLocalRefreshResult(tuple(records), 0, 0, 0)
                changed = 0
                error = f"{type(exc).__name__}: {exc}"
            self.events.put(("portable_local_versions_done", (result, changed, error)))

        threading.Thread(
            target=worker,
            name="wdp-portable-local-versions",
            daemon=True,
        ).start()

    def _finish_portable_local_refresh(
        self,
        result: PortableLocalRefreshResult,
        changed: int | None,
        error: str,
    ) -> None:
        self._portable_local_refresh_active = False
        self._schedule_idle_date_sleuth()
        if self._closing:
            return
        if error:
            self._portable_local_refresh_completed = True
            self._append_log(f"Portable version confirmation failed: {error}")
            self.logger.event("portable_local_version_refresh_failed", error=error)
        elif changed is None:
            # A manual scan or cache clear won the revision race. Retry once the
            # newer portable inventory is settled instead of restoring stale data.
            self._portable_local_refresh_pending = True
            self.logger.event(
                "portable_local_version_refresh_superseded",
                reason="portable inventory changed during local version probes",
            )
            self.root.after(75, self._request_portable_local_refresh)
            return
        else:
            self._portable_local_refresh_completed = True
            records = self.portable_inventory.records()
            self._merge_portable_records(records)
            self.items = self._scan_view_items[self._last_scan_all_packages]
            self._rebuild_tree()
            self._refresh_scan_summary_counts()
            self._append_log(
                f"Portable versions confirmed: {result.checked} app(s) checked"
                + (
                    f"; {result.version_changes} local version change(s) detected"
                    if result.version_changes
                    else "; no local version changes"
                )
                + (
                    f"; {result.homepage_changes} homepage(s) discovered"
                    if result.homepage_changes
                    else ""
                )
            )
            self.logger.event(
                "portable_local_version_refresh_finished",
                checked=result.checked,
                cache_records_changed=changed,
                version_changes=result.version_changes,
                homepage_changes=result.homepage_changes,
            )
        self._portable_local_refresh_pending = False
        self._start_portable_catalog_refresh()
        if not self._icon_background_sweep_active:
            self._start_background_details_icon_sweep()

    def _finish_portable_scan(
        self, result: PortableScanResult | None, error: str
    ) -> None:
        self._portable_scan_active = False
        self.progress.stop()
        self.progress.configure(mode="determinate")
        self._set_progress_value(0, animate=False)
        self._set_busy(False)
        if error or result is None:
            self._notify_user(
                f"Portable scan could not be completed: {error or 'unknown error'}",
                level="error",
                summary="Portable scan failed; details were logged",
            )
            self.logger.event("portable_scan_failed", error=error)
            return
        if result.cancelled:
            self.summary_var.set("Portable scan stopped; the previous saved results were kept")
            self._append_log(
                f"Portable scan stopped after checking {result.files_checked} executable(s); "
                "previous saved results were kept"
            )
            self.logger.event(
                "portable_scan_cancelled",
                root=result.root,
                files_checked=result.files_checked,
                directories_checked=result.directories_checked,
                duration_seconds=result.duration_seconds,
            )
            return
        records = self.portable_inventory.records()
        portable_items, _portable_updates = self._merge_portable_records(records)
        # A portable scan must not pull the user away from the catalog they
        # deliberately chose while it was running.
        self.items = self._scan_view_items[self._last_scan_all_packages]
        self._show_scan_view(self._last_scan_all_packages, force=True)
        truncation = " (bounded scan limit reached)" if result.truncated else ""
        access = (
            f"; {result.access_errors} inaccessible location(s) skipped"
            if result.access_errors
            else ""
        )
        self._append_log(
            f"Portable scan complete: {len(result.records)} app(s) found under "
            f"{result.root} in {result.duration_seconds:.1f}s; "
            f"{result.files_checked} executable(s) checked; "
            f"{sum(bool(record.catalog_available_version) for record in result.records)} "
            f"with a cached release-version clue"
            + (
                f"; {result.review_candidates} lower-confidence candidate(s) withheld"
                if result.review_candidates
                else ""
            )
            + (
                "; PE-metadata budget reached, so some executables were not evaluated"
                if result.metadata_budget_exhausted
                else ""
            )
            + f"{access}{truncation}"
        )
        if result.broad_scan:
            self._append_log(
                "Broad-drive portable rules applied: account-private, installed-app, "
                "manager-owned, and staging trees were excluded"
            )
        if self.debug_mode and result.review_samples:
            for sample in result.review_samples:
                self._append_log(
                    "Withheld portable candidate: "
                    f"{sample.get('name', '(unnamed)')} "
                    f"[score {sample.get('score', '?')}] at "
                    f"{sample.get('executable', '(unknown path)')}; "
                    + "; ".join(str(reason) for reason in sample.get("reasons", ())),
                    show_in_ui=False,
                )
        self.logger.event(
            "portable_scan_finished",
            root=result.root,
            scan_scope="broad-drive" if result.broad_scan else "bounded-folder",
            found=len(result.records),
            cached_total=len(portable_items),
            files_checked=result.files_checked,
            directories_checked=result.directories_checked,
            metadata_probes=result.metadata_probes,
            metadata_budget_exhausted=result.metadata_budget_exhausted,
            access_errors=result.access_errors,
            truncated=result.truncated,
            lower_confidence_candidates_withheld=result.review_candidates,
            rejected_candidates=result.rejected_candidates,
            review_candidate_samples=list(result.review_samples),
            rejection_reason_counts=dict(result.rejection_reason_counts),
            pruned_directory_reason_counts=dict(
                result.pruned_directory_reason_counts
            ),
            duration_seconds=result.duration_seconds,
            items=[item_diagnostic_fields(item) for item in portable_items],
        )
        if self._portable_local_refresh_pending and not self._portable_local_refresh_completed:
            self._request_portable_local_refresh()
        else:
            self._start_portable_catalog_refresh()
        self._schedule_idle_date_sleuth()

    def _start_portable_catalog_refresh(self) -> None:
        if (
            self._portable_catalog_refresh_active
            or self._portable_cache_verification_active
            or self._portable_local_refresh_active
            or self._portable_local_refresh_pending
            or self._closing
        ):
            return
        records, revision = self.portable_inventory.catalog_snapshot()
        if not any(not portable_catalog_metadata_is_fresh(record) for record in records):
            return
        self._portable_catalog_refresh_active = True
        self.logger.event(
            "portable_catalog_refresh_started",
            cached_records=len(records),
        )

        def worker() -> None:
            try:
                with _exposed_cloud_placeholders_for_current_thread():
                    result = refresh_portable_catalog_records(records)
                changed = self.portable_inventory.update_records(
                    result.records,
                    expected_revision=revision,
                )
                error = ""
            except Exception as exc:
                result = PortableCatalogRefreshResult(tuple(records), 0, 0, len(records))
                changed = 0
                error = f"{type(exc).__name__}: {exc}"
            self.events.put(
                ("portable_catalog_done", (result, changed, error))
            )

        threading.Thread(
            target=worker,
            name="wdp-portable-catalog",
            daemon=True,
        ).start()

    def _finish_portable_catalog_refresh(
        self,
        result: PortableCatalogRefreshResult,
        changed: int | None,
        error: str,
    ) -> None:
        self._portable_catalog_refresh_active = False
        self._schedule_idle_date_sleuth()
        if self._closing:
            return
        if error:
            self._append_log(
                f"Portable catalog lookup could not be completed: {error}",
                show_in_ui=False,
            )
            self.logger.event("portable_catalog_refresh_failed", error=error)
            return
        if changed is None:
            self.logger.event(
                "portable_catalog_refresh_superseded",
                reason="portable inventory changed while release metadata was being checked",
            )
            if any(
                not portable_catalog_metadata_is_fresh(record)
                for record in self.portable_inventory.records()
            ):
                self.root.after(50, self._start_portable_catalog_refresh)
            return
        records = self.portable_inventory.records()
        _portable_items, portable_updates = self._merge_portable_records(records)
        self.items = self._scan_view_items[self._last_scan_all_packages]
        self._rebuild_tree()
        self._refresh_scan_summary_counts()
        if result.checked:
            homepage_count = sum(
                bool(record.homepage or record.catalog_homepage) for record in records
            )
            self._append_log(
                f"Portable release check: {result.matched} with a trusted version clue; "
                f"{result.unavailable} without one; {homepage_count} homepage(s) known"
            )
        self.logger.event(
            "portable_catalog_refresh_finished",
            checked=result.checked,
            matched=result.matched,
            unavailable=result.unavailable,
            cache_records_changed=changed,
            update_advisories=len(portable_updates),
        )
        if any(
            not portable_catalog_metadata_is_fresh(record)
            for record in self.portable_inventory.records()
        ):
            self.root.after(50, self._start_portable_catalog_refresh)

    def _start_scan(self, *, origin: str = "manual") -> None:
        if self._scan_active:
            return
        concurrent_update = self.busy and self._busy_kind == "update"
        if self.busy and not concurrent_update:
            return
        enabled = dict(self.settings.data["providers"])
        self._scan_expected_provider_keys = {
            key
            for key, provider in self.providers.items()
            if key != PORTABLE_PROVIDER_KEY
            and enabled.get(key, provider.default_enabled)
        }
        self._scan_current_provider_keys.clear()
        self._scan_provider_inventory_batches.clear()
        self._scan_windows_package_dates.clear()
        self._provisional_inventory_keys.update(
            item.key
            for item in self._scan_view_items[True].values()
            if item.provider != PORTABLE_PROVIDER_KEY
        )
        self._path_refresh_report = merge_windows_path_refresh_reports(
            self._path_refresh_report,
            refresh_process_path_from_windows_environment(),
        )
        self._reset_idle_date_sleuth()
        self._enrichment_generation += 1
        self._winget_enrichment_active = False
        self._scan_active = True
        self._active_scan_owns_busy = not concurrent_update
        self._scan_progress_determinate = False
        self._scan_generation += 1
        generation = self._scan_generation
        self._active_scan_generation = generation
        self._active_scan_origin = origin
        last_scan_completed_at = self._last_scan_completed_at
        if last_scan_completed_at is not None and last_scan_completed_at.tzinfo is None:
            last_scan_completed_at = last_scan_completed_at.astimezone()
        age_seconds = (
            max(
                0.0,
                (
                    dt.datetime.now().astimezone() - last_scan_completed_at
                ).total_seconds(),
            )
            if last_scan_completed_at is not None
            else None
        )
        self.logger.event(
            "scan_requested",
            scan_generation=generation,
            origin=origin,
            seconds_since_previous_scan=(
                round(age_seconds, 3) if age_seconds is not None else None
            ),
        )
        self._mark_scan_refresh_needed("Scan in progress")
        self._scan_cancel_requested.clear()
        if self._active_scan_owns_busy:
            self._set_busy(True, "Refreshing updates and installed packages", kind="scan")
            self.progress.configure(mode="indeterminate")
            self.progress.start(INDETERMINATE_PROGRESS_INTERVAL_MS)
            self.summary_var.set("Refreshing updates and complete installed-package inventory…")
            self._append_log("Refreshing updates and installed packages…")
        else:
            self._refresh_scan_button_style()
            self._append_log(
                "Rescanning while updates continue; active package managers retain their "
                "previous catalog while the others refresh"
            )
        if self._last_scan_all_packages:
            self._rebuild_tree(prime_cached_first_paint=True)
        if not concurrent_update:
            self._refresh_scan_summary_counts()
        self._active_scan_settings_snapshot = {
            "providers": enabled,
            "auto_elevate": bool(self.settings.data.get("auto_elevate", True)),
        }
        provider_snapshots = {
            key: (
                tuple(
                    dataclasses.replace(item)
                    for item in self._scan_view_items[False].values()
                    if item.provider == key
                ),
                tuple(
                    dataclasses.replace(item)
                    for item in self._scan_view_items[True].values()
                    if item.provider == key
                ),
            )
            for key in self.providers
        }
        post_update_verification = (
            {
                key: {
                    "item": dict(record.get("item", {})),
                    "result": dict(record.get("result", {})),
                }
                for key, record in self._verification_results.items()
            }
            if origin == "post-update-verification"
            else {}
        )
        self._start_guarded_worker(
            lambda: self._scan_worker(
                generation,
                enabled,
                concurrent_update,
                provider_snapshots,
                post_update_verification,
                dict(self._provider_snapshot_refreshed_at),
            ),
            name=f"wdp-scan-{generation}",
            operation="scan",
            generation=generation,
        )

    def _scan_worker(
        self,
        generation: int = 0,
        enabled: Mapping[str, bool] | None = None,
        started_during_update: bool = False,
        provider_snapshots: Mapping[
            str, tuple[Sequence[UpdateItem], Sequence[UpdateItem]]
        ]
        | None = None,
        post_update_verification: Mapping[str, Mapping[str, Any]] | None = None,
        provider_snapshot_refreshed_at: Mapping[str, float] | None = None,
    ) -> None:
        scan_clock = time.perf_counter()
        found_updates: list[UpdateItem] = []
        found_packages: list[UpdateItem] = []
        errors: list[str] = []
        failed_provider_keys: set[str] = set()
        enabled = dict(enabled if enabled is not None else self.settings.data["providers"])
        provider_map = build_providers()
        provider_availability = {
            key: provider.available() for key, provider in provider_map.items()
        }
        providers = [
            provider
            for key, provider in provider_map.items()
            if enabled.get(key, provider.default_enabled) and provider_availability[key]
        ]
        unavailable_provider_keys = material_unavailable_provider_keys(
            provider_map,
            enabled,
            provider_availability,
        )
        self.events.put(
            (
                "scan_plan",
                (
                    generation,
                    tuple(
                        dict.fromkeys(
                            [
                                *(provider.key for provider in providers),
                                *sorted(unavailable_provider_keys),
                            ]
                        )
                    ),
                ),
            )
        )
        provider_timings: list[dict[str, Any]] = []
        cancelled_provider_keys: set[str] = set()
        deferred_provider_keys: set[str] = set()
        duration_hints = dict(self._provider_duration_hints)
        provider_snapshots = provider_snapshots or {}
        post_update_verification = post_update_verification or {}
        provider_snapshot_refreshed_at = provider_snapshot_refreshed_at or {}
        icon_catalog = dict(getattr(self, "_icon_catalog_entries", {}))
        attempted_provider_keys = {
            str(record.get("item", {}).get("provider", ""))
            for record in post_update_verification.values()
            if str(record.get("item", {}).get("provider", ""))
        }
        scheduled_provider_keys = {provider.key for provider in providers}
        recent_snapshot_ages = (
            recent_untouched_provider_snapshot_ages(
                scheduled_provider_keys,
                attempted_provider_keys,
                provider_snapshot_refreshed_at,
                now=time.monotonic(),
            )
            if post_update_verification
            else {}
        )
        unavailable_attempted_provider_keys = (
            attempted_provider_keys - scheduled_provider_keys
        )
        for provider_key in sorted(unavailable_attempted_provider_keys):
            provider = provider_map.get(provider_key)
            provider_label = provider.label if provider is not None else provider_key
            self.events.put(
                (
                    "post_update_provider_updates",
                    (
                        generation,
                        provider_key,
                        provider_label,
                        (),
                        "provider is disabled or unavailable",
                        0.0,
                    ),
                )
            )
        if unavailable_attempted_provider_keys:
            self.logger.event(
                "post_update_attempted_providers_unavailable",
                scan_generation=generation,
                provider_keys=sorted(unavailable_attempted_provider_keys),
            )

        def provider_phase(
            provider: Provider,
            callback: Callable[[], list[UpdateItem]],
        ) -> tuple[list[UpdateItem], str, list[str], list[dict[str, Any]], float]:
            provider.warnings.clear()
            provider.suppressed_updates.clear()
            if not hasattr(provider, "phase_incomplete_reasons"):
                provider.phase_incomplete_reasons = []
            provider.phase_incomplete_reasons.clear()
            phase_started = time.perf_counter()
            try:
                with background_command_process_priority():
                    items = stable_identity_instances(callback())
                error = (
                    "incomplete provider result: "
                    + "; ".join(provider.phase_incomplete_reasons)
                    if provider.phase_incomplete_reasons
                    else ""
                )
            except Exception as exc:
                items = []
                error = f"{type(exc).__name__}: {exc}"
            warnings = list(provider.warnings)
            suppressions = [dict(value) for value in provider.suppressed_updates]
            provider.warnings.clear()
            provider.suppressed_updates.clear()
            provider.phase_incomplete_reasons.clear()
            return (
                items,
                error,
                warnings,
                suppressions,
                round(time.perf_counter() - phase_started, 3),
            )

        def scan_provider(index: int, provider: Provider) -> dict[str, Any]:
            started = time.perf_counter()
            if self._scan_cancel_requested.is_set():
                return {
                    "index": index,
                    "provider": provider,
                    "updates": [],
                    "packages": [],
                    "update_error": "",
                    "inventory_error": "",
                    "update_duration_seconds": 0.0,
                    "inventory_duration_seconds": 0.0,
                    "duration_seconds": 0.0,
                    "update_warnings": [],
                    "inventory_warnings": [],
                    "update_suppressions": [],
                    "inventory_suppressions": [],
                    "cancelled": True,
                    "deferred": False,
                    "reused_previous": False,
                }
            snapshot_updates, snapshot_packages = provider_snapshots.get(provider.key, ((), ()))
            if provider.key in recent_snapshot_ages:
                return {
                    "index": index,
                    "provider": provider,
                    "updates": [dataclasses.replace(item) for item in snapshot_updates],
                    "packages": [dataclasses.replace(item) for item in snapshot_packages],
                    "update_error": "",
                    "inventory_error": "",
                    "update_duration_seconds": 0.0,
                    "inventory_duration_seconds": 0.0,
                    "duration_seconds": round(time.perf_counter() - started, 3),
                    "update_warnings": [],
                    "inventory_warnings": [],
                    "update_suppressions": [],
                    "inventory_suppressions": [],
                    "cancelled": False,
                    "deferred": False,
                    "reused_previous": True,
                    "reused_recent": True,
                    "reused_snapshot_age_seconds": round(
                        recent_snapshot_ages[provider.key], 3
                    ),
                }
            operation_lock = self._provider_operation_locks[provider.key]
            active_snapshot = dict(self._active_operation_items)
            completed_keys = {
                str(entry.get("key", "")) for entry in self._active_operation_results
            }
            pending_provider_keys = {
                key for key, item in active_snapshot.items() if item.provider == provider.key
            } - completed_keys
            defer_for_active_update = started_during_update and bool(pending_provider_keys)
            acquired = False if defer_for_active_update else operation_lock.acquire(blocking=False)
            if started_during_update and not acquired:
                return {
                    "index": index,
                    "provider": provider,
                    "updates": [dataclasses.replace(item) for item in snapshot_updates],
                    "packages": [dataclasses.replace(item) for item in snapshot_packages],
                    "update_error": "",
                    "inventory_error": "",
                    "update_duration_seconds": 0.0,
                    "inventory_duration_seconds": 0.0,
                    "duration_seconds": round(time.perf_counter() - started, 3),
                    "update_warnings": [],
                    "inventory_warnings": [],
                    "update_suppressions": [],
                    "inventory_suppressions": [],
                    "cancelled": False,
                    "deferred": True,
                    "reused_previous": bool(snapshot_updates or snapshot_packages),
                }
            while not acquired and not self._scan_cancel_requested.is_set():
                if operation_lock.acquire(timeout=0.1):
                    acquired = True
                    break
            if not acquired:
                return {
                    "index": index,
                    "provider": provider,
                    "updates": [],
                    "packages": [],
                    "update_error": "",
                    "inventory_error": "",
                    "update_duration_seconds": 0.0,
                    "inventory_duration_seconds": 0.0,
                    "duration_seconds": round(time.perf_counter() - started, 3),
                    "update_warnings": [],
                    "inventory_warnings": [],
                    "update_suppressions": [],
                    "inventory_suppressions": [],
                    "cancelled": True,
                    "deferred": False,
                    "reused_previous": False,
                }

            try:
                observation_started_at = utc_now_iso()
                (
                    updates,
                    update_error,
                    update_warnings,
                    update_suppressions,
                    update_duration,
                ) = provider_phase(provider, provider.discover)
                if provider.key in attempted_provider_keys:
                    self.events.put(
                        (
                            "post_update_provider_updates",
                            (
                                generation,
                                provider.key,
                                provider.label,
                                tuple(dataclasses.replace(item) for item in updates),
                                update_error,
                                update_duration,
                            ),
                        )
                    )
                (
                    packages,
                    inventory_error,
                    inventory_warnings,
                    inventory_suppressions,
                    inventory_duration,
                ) = provider_phase(provider, provider.discover_all)
                observation_finished_at = utc_now_iso()
                observation_finished_monotonic = time.monotonic()
                duration = round(time.perf_counter() - started, 3)
                return {
                    "index": index,
                    "provider": provider,
                    "updates": updates,
                    "packages": packages,
                    "update_error": update_error,
                    "inventory_error": inventory_error,
                    "update_duration_seconds": update_duration,
                    "inventory_duration_seconds": inventory_duration,
                    "observation_started_at": observation_started_at,
                    "observation_finished_at": observation_finished_at,
                    "observation_finished_monotonic": observation_finished_monotonic,
                    "duration_seconds": duration,
                    "update_warnings": update_warnings,
                    "inventory_warnings": inventory_warnings,
                    "update_suppressions": update_suppressions,
                    "inventory_suppressions": inventory_suppressions,
                    "cancelled": False,
                    "deferred": False,
                    "reused_previous": False,
                }
            finally:
                operation_lock.release()

        def emit_scan_log(message: str) -> None:
            self.events.put(("scan_log", (generation, message)))

        def emit_scan_notice(provider_key: str, phase: str, message: str) -> None:
            self.events.put(
                ("scan_notice", (generation, provider_key, phase, message))
            )

        if providers and not self._scan_cancel_requested.is_set():
            max_workers = min(3, len(providers))
            scheduled_providers = duration_prioritized_providers(providers, duration_hints)
            scheduled_providers.sort(
                key=lambda pair: pair[1].key not in attempted_provider_keys
            )
            self.logger.event(
                "provider_scan_scheduled",
                scan_mode="combined",
                scan_generation=generation,
                max_workers=max_workers,
                child_process_priority="below-normal",
                canonical_order=[provider.key for provider in providers],
                scheduled_order=[provider.key for _index, provider in scheduled_providers],
                attempted_provider_keys=sorted(attempted_provider_keys),
                recent_snapshot_reuse={
                    key: round(age, 3) for key, age in sorted(recent_snapshot_ages.items())
                },
                recent_snapshot_grace_seconds=POST_UPDATE_PROVIDER_REUSE_GRACE_SECONDS,
                duration_hints={
                    key: round(value, 3) for key, value in duration_hints.items() if value > 0
                },
            )
            with concurrent.futures.ThreadPoolExecutor(max_workers=max_workers) as executor:
                futures = [
                    executor.submit(scan_provider, index, provider)
                    for index, provider in scheduled_providers
                ]
                results = []
                completed_providers = 0
                for future in concurrent.futures.as_completed(futures):
                    result = future.result()
                    results.append(result)
                    provider = result["provider"]
                    completed_providers += 1
                    inventory_current = bool(
                        not result["cancelled"]
                        and not result["deferred"]
                        and not result["inventory_error"]
                    )
                    self.events.put(
                        (
                            "scan_inventory_provider",
                            (
                                generation,
                                provider.key,
                                provider.label,
                                tuple(
                                    dataclasses.replace(item)
                                    for item in result["packages"]
                                ),
                                inventory_current,
                                not bool(result.get("reused_recent")),
                                dict(getattr(provider, "native_package_dates", {}))
                                if inventory_current else {},
                            ),
                        )
                    )
                    self.events.put(
                        (
                            "scan_progress",
                            (
                                generation,
                                completed_providers,
                                len(providers),
                                provider.label,
                                started_during_update,
                            ),
                        )
                    )
                    if result["cancelled"]:
                        emit_scan_log(f"{provider.label}: skipped after stop request")
                        continue
                    updates = list(result["updates"])
                    packages = list(result["packages"])
                    if result["deferred"]:
                        retained = len(updates) + len(packages)
                        emit_scan_log(
                            f"{provider.label}: retained {retained} previous catalog row(s) "
                            "while its update queue is active"
                        )
                        continue
                    if result.get("reused_recent"):
                        snapshot_age = float(result.get("reused_snapshot_age_seconds", 0.0))
                        emit_scan_log(
                            f"{provider.label}: retained recent snapshot "
                            f"({snapshot_age:.0f}s old; {len(updates)} update row(s); "
                            f"{len(packages)} package row(s))"
                        )
                        continue
                    update_label = "update" if len(updates) == 1 else "updates"
                    package_label = "package" if len(packages) == 1 else "packages"
                    suppressed_count = len(result["update_suppressions"])
                    suppressed_text = (
                        f"; {suppressed_count} non-actionable update offer(s) suppressed"
                        if suppressed_count
                        else ""
                    )
                    emit_scan_log(
                        f"{provider.label}: {len(updates)} {update_label}; "
                        f"{len(packages)} {package_label}{suppressed_text} "
                        f"({float(result['duration_seconds']):.1f}s)"
                    )
            for result in sorted(results, key=lambda entry: int(entry["index"])):
                provider = result["provider"]
                updates = list(result["updates"])
                packages = list(result["packages"])
                duration = float(result["duration_seconds"])
                update_duration = float(result["update_duration_seconds"])
                inventory_duration = float(result["inventory_duration_seconds"])
                update_warnings = [str(warning) for warning in result["update_warnings"]]
                inventory_warnings = [
                    str(warning)
                    for warning in result["inventory_warnings"]
                    if str(warning) not in update_warnings
                ]
                update_suppressions = [
                    dict(value) for value in result["update_suppressions"]
                ]
                inventory_suppressions = [
                    dict(value) for value in result["inventory_suppressions"]
                ]
                update_error = str(result["update_error"])
                inventory_error = str(result["inventory_error"])
                cancelled = bool(result["cancelled"])
                deferred = bool(result["deferred"])
                reused_recent = bool(result.get("reused_recent"))
                reused_snapshot_age = float(
                    result.get("reused_snapshot_age_seconds", 0.0)
                )
                provider_timings.append(
                    {
                        "key": provider.key,
                        "label": provider.label,
                        "duration_seconds": duration,
                        "update_count": len(updates),
                        "package_count": len(packages),
                        "update_duration_seconds": update_duration,
                        "inventory_duration_seconds": inventory_duration,
                        "observation_started_at": result.get("observation_started_at", ""),
                        "observation_finished_at": result.get("observation_finished_at", ""),
                        "observation_finished_monotonic": result.get("observation_finished_monotonic", 0.0),
                        "warning_count": len(update_warnings) + len(inventory_warnings),
                        "suppressed_update_count": len(update_suppressions),
                        "recent_inventory_hits": int(
                            getattr(provider, "recent_inventory_hits", 0)
                        ),
                        "update_error": update_error,
                        "inventory_error": inventory_error,
                        "cancelled": cancelled,
                        "deferred": deferred,
                        "reused_previous": bool(result["reused_previous"]),
                        "reused_recent": reused_recent,
                        "reused_snapshot_age_seconds": reused_snapshot_age,
                    }
                )
                if cancelled:
                    cancelled_provider_keys.add(provider.key)
                    continue
                if deferred:
                    deferred_provider_keys.add(provider.key)
                if update_error:
                    message = f"{provider.label} updates: {update_error}"
                    errors.append(message)
                    failed_provider_keys.add(provider.key)
                if inventory_error:
                    message = f"{provider.label} inventory: {inventory_error}"
                    errors.append(message)
                found_updates.extend(updates)
                found_packages.extend(packages)
                for warning in update_warnings:
                    emit_scan_notice(
                        provider.key,
                        "update",
                        f"{provider.label} update warning: {warning}",
                    )
                for warning in inventory_warnings:
                    emit_scan_notice(
                        provider.key,
                        "inventory",
                        f"{provider.label} inventory warning: {warning}",
                    )
                self.logger.event(
                    "provider_scan_finished",
                    provider={
                        "key": provider.key,
                        "label": provider.label,
                        "configured_executable": provider.executable,
                        "resolved_executable": (
                            shutil.which(provider.executable) if provider.executable else ""
                        ),
                    },
                    duration_seconds=duration,
                    update_count=len(updates),
                    package_count=len(packages),
                    update_duration_seconds=update_duration,
                    inventory_duration_seconds=inventory_duration,
                    scan_mode="combined",
                    scan_generation=generation,
                    update_warning_count=len(update_warnings),
                    inventory_warning_count=len(inventory_warnings),
                    suppressed_updates=update_suppressions,
                    inventory_suppressions=inventory_suppressions,
                    recent_inventory_hits=int(getattr(provider, "recent_inventory_hits", 0)),
                    update_error=update_error,
                    inventory_error=inventory_error,
                    deferred=deferred,
                    reused_previous=bool(result["reused_previous"]),
                    reused_recent=reused_recent,
                    reused_snapshot_age_seconds=reused_snapshot_age,
                )
        scan_duration = round(time.perf_counter() - scan_clock, 3)
        scan_cancelled = self._scan_cancel_requested.is_set() or bool(
            cancelled_provider_keys
        )
        self.events.put(
            (
                "scan_done",
                (
                    found_updates,
                    found_packages,
                    errors,
                    len(providers),
                    failed_provider_keys,
                    provider_timings,
                    scan_duration,
                    generation,
                    scan_cancelled,
                    cancelled_provider_keys,
                    deferred_provider_keys,
                    started_during_update,
                    unavailable_provider_keys,
                    changed_icon_catalog_keys(icon_catalog, [*found_updates, *found_packages]),
                ),
            )
        )

    def _show_scan_progress(
        self,
        generation: int,
        completed: int,
        total: int,
        provider_label: str,
        started_during_update: bool,
    ) -> None:
        """Show provider completion without disturbing an overlapping update run."""

        if (
            self._closing
            or generation != self._active_scan_generation
            or not self._scan_active
            or started_during_update
        ):
            return
        total = max(1, int(total))
        completed = max(0, min(total, int(completed)))
        self._activity_base = (
            f"Refreshing package catalogs — {completed}/{total} checked; "
            f"latest: {provider_label}"
        )
        if self._native_window_interaction_active():
            # Consume provider progress and keep the semantic counters current,
            # but avoid Tcl progress/summary work during an exclusive move or
            # size gesture. The next provider or final result paints the truth.
            return
        if not getattr(self, "_scan_progress_determinate", False):
            self.progress.stop()
            self.progress.configure(mode="determinate")
            self._scan_progress_determinate = True
        self._set_progress_value(completed * 100 / total)
        self._refresh_scan_summary_counts()

    def _apply_scan_plan(
        self,
        generation: int,
        provider_keys: Sequence[str],
    ) -> None:
        """Count runnable providers plus material unavailable coverage, not optional gaps."""

        if (
            self._closing
            or generation != self._active_scan_generation
            or not self._scan_active
        ):
            return
        expected = {
            str(key)
            for key in provider_keys
            if str(key) in self.providers and str(key) != PORTABLE_PROVIDER_KEY
        }
        self._scan_expected_provider_keys = expected
        self._scan_current_provider_keys.intersection_update(expected)
        self._scan_provider_inventory_batches = {
            key: items
            for key, items in self._scan_provider_inventory_batches.items()
            if key in expected
        }
        if not (self.busy and self._busy_kind == "update"):
            self._refresh_scan_summary_counts()
        self.logger.event(
            "installed_inventory_scan_plan_applied",
            scan_generation=generation,
            expected_providers=sorted(expected),
            expected_provider_count=len(expected),
        )

    def _apply_scan_inventory_provider(
        self,
        generation: int,
        provider_key: str,
        provider_label: str,
        packages: Sequence[UpdateItem],
        inventory_current: bool,
        publish_inventory: bool = True,
        windows_package_dates: Mapping[str, tuple[str, str]] | None = None,
    ) -> None:
        """Publish one provider batch; its following progress event paints summary once."""

        if (
            self._closing
            or generation != self._active_scan_generation
            or not self._scan_active
        ):
            return
        if not inventory_current:
            return
        if provider_key == MICROSOFT_STORE_PROVIDER_KEY and windows_package_dates:
            self._scan_windows_package_dates = dict(windows_package_dates)
        # The scan worker already detached this event payload from provider-owned
        # records. Retain that snapshot instead of copying every row again on Tk.
        detached = tuple(packages)
        self._scan_current_provider_keys.add(provider_key)
        self._scan_provider_inventory_batches[provider_key] = detached
        if not publish_inventory:
            self.logger.event(
                "installed_inventory_provider_snapshot_retained",
                scan_generation=generation,
                provider=provider_key,
                provider_label=provider_label,
                package_count=len(detached),
                current_provider_count=len(
                    self._scan_current_provider_keys.intersection(
                        self._scan_expected_provider_keys
                    )
                ),
                expected_provider_count=len(self._scan_expected_provider_keys),
            )
            return
        joint_keys = self._scan_expected_provider_keys.intersection(
            {WingetProvider.key, MICROSOFT_STORE_PROVIDER_KEY}
        )
        if provider_key in joint_keys:
            if not joint_keys.issubset(self._scan_current_provider_keys):
                return
            replacement_keys = joint_keys
            replacement_items = deduplicate_microsoft_store_inventory(
                [
                    item
                    for key in sorted(joint_keys)
                    for item in self._scan_provider_inventory_batches.get(key, ())
                ]
            )
        else:
            replacement_keys = {provider_key}
            replacement_items = list(detached)
        apply_windows_package_dates(
            replacement_items, getattr(self, "_scan_windows_package_dates", {}),
        )
        apply_known_product_variant_names(replacement_items)
        reuse_cached_service_dates(replacement_items, self._observation_inventory_snapshot.items)
        if self._icon_catalog_loaded:
            self._apply_icon_catalog_to_items(replacement_items)
        replaced_keys = {
            key
            for key, item in self._scan_view_items[True].items()
            if item.provider in replacement_keys
        }
        self._scan_view_items[True] = replace_inventory_provider_rows(
            self._scan_view_items[True],
            replacement_items,
            replacement_keys,
        )
        self._provisional_inventory_keys.difference_update(replaced_keys)
        self._provisional_inventory_keys.difference_update(
            item.key for item in replacement_items
        )
        if self._last_scan_all_packages:
            self.items = self._scan_view_items[True]
            self._schedule_rebuild_tree(prime_cached_first_paint=True)
        for listener in tuple(getattr(self, "_details_refinement_listeners", ())):
            with contextlib.suppress(self.tk.TclError):
                listener("")
        self.logger.event(
            "installed_inventory_provider_published",
            scan_generation=generation,
            provider=provider_key,
            provider_label=provider_label,
            replacement_providers=sorted(replacement_keys),
            package_count=len(replacement_items),
            current_provider_count=len(
                self._scan_current_provider_keys.intersection(
                    self._scan_expected_provider_keys
                )
            ),
            expected_provider_count=len(self._scan_expected_provider_keys),
        )

    def _write_installed_inventory_cache_async(
        self,
        snapshot: InstalledInventorySnapshot,
        scan_generation: int,
    ) -> None:
        """Persist the already-detached observation snapshot off the Tk thread.

        The caller owns these rows and observation maps and publishes them once;
        later scans replace the snapshot, never mutate it. Keep this exact
        snapshot in the closure so a newer scan cannot change an in-flight write.
        """

        scanned_at = snapshot.scanned_at
        if scanned_at is None:
            raise ValueError("cannot persist an inventory without its scan timestamp")
        self._installed_inventory_cache_write_generation += 1
        write_generation = self._installed_inventory_cache_write_generation
        self._installed_inventory_cache_write_active = True

        def worker() -> None:
            error = ""
            try:
                self.installed_inventory.replace(
                    snapshot.items,
                    snapshot.provider_keys,
                    scanned_at,
                    snapshot.update_observations,
                    snapshot.provider_scanned_at,
                    snapshot.installation_observations,
                    provider_started_at=snapshot.provider_started_at,
                    write_generation=write_generation,
                )
            except (OSError, TypeError, ValueError) as exc:
                error = f"{type(exc).__name__}: {exc}"
            self.events.put(
                (
                    "installed_inventory_cached",
                    (
                        write_generation,
                        scan_generation,
                        len(snapshot.items),
                        error,
                    ),
                )
            )

        threading.Thread(
            target=worker,
            name=f"wdp-inventory-cache-{write_generation}",
            daemon=True,
        ).start()

    def _finish_installed_inventory_cache_write(
        self,
        write_generation: int,
        scan_generation: int,
        item_count: int,
        error: str,
    ) -> None:
        if write_generation == self._installed_inventory_cache_write_generation:
            self._installed_inventory_cache_write_active = False
        if error:
            self._append_log(
                f"Installed inventory cache could not be saved: {error}",
                show_in_ui=False,
            )
        self.logger.event(
            "installed_inventory_cache_finished",
            write_generation=write_generation,
            scan_generation=scan_generation,
            item_count=item_count,
            success=not error,
            error=error,
        )

    def _finish_scan(
        self,
        found_updates: list[UpdateItem],
        found_packages: list[UpdateItem],
        errors: list[str],
        provider_count: int,
        failed_provider_keys: set[str],
        provider_timings: list[dict[str, Any]] | None = None,
        scan_duration_seconds: float = 0.0,
        generation: int = 0,
        scan_cancelled: bool = False,
        cancelled_provider_keys: set[str] | None = None,
        deferred_provider_keys: set[str] | None = None,
        started_during_update: bool = False,
        unavailable_provider_keys: set[str] | None = None,
        changed_icon_keys: set[str] | None = None,
    ) -> None:
        if generation and generation != self._active_scan_generation:
            self.logger.event(
                "superseded_scan_result_ignored",
                generation=generation,
                active_generation=self._active_scan_generation,
                scan_mode="combined",
            )
            return
        self._invalidate_item_icon_caches(set(changed_icon_keys or ()))
        finish_stage_started = time.perf_counter()
        finish_stages: dict[str, float] = {}

        def finish_checkpoint(name: str) -> None:
            nonlocal finish_stage_started
            now = time.perf_counter()
            finish_stages[name] = round((now - finish_stage_started) * 1000.0, 3)
            finish_stage_started = now

        failed_provider_keys = set(failed_provider_keys)
        deferred_provider_keys = set(deferred_provider_keys or ())
        unavailable_provider_keys = set(unavailable_provider_keys or ())
        if scan_cancelled:
            failed_provider_keys.update(cancelled_provider_keys or ())
        attempted_verification_provider_keys = {
            str(record.get("item", {}).get("provider", ""))
            for record in self._verification_results.values()
            if str(record.get("item", {}).get("provider", ""))
        }
        refreshed_update_provider_keys = {
            str(timing.get("key", ""))
            for timing in provider_timings or []
            if not timing.get("cancelled")
            and not timing.get("deferred")
            and not timing.get("reused_recent")
            and not timing.get("update_error")
            and not timing.get("inventory_error")
        }
        scheduled_timing_provider_keys = {
            str(timing.get("key", ""))
            for timing in provider_timings or []
            if str(timing.get("key", ""))
        }
        unavailable_attempted_provider_keys = (
            attempted_verification_provider_keys - scheduled_timing_provider_keys
        )
        verification_failed_provider_keys = {
            *failed_provider_keys,
            *unavailable_provider_keys,
            *(
                attempted_verification_provider_keys
                - refreshed_update_provider_keys
            ),
        }
        recent_snapshot_provider_keys = {
            str(timing.get("key", ""))
            for timing in provider_timings or []
            if timing.get("reused_recent") and str(timing.get("key", ""))
        }
        provider_snapshot_refreshed_at = getattr(
            self, "_provider_snapshot_refreshed_at", None
        )
        if provider_snapshot_refreshed_at is None:
            provider_snapshot_refreshed_at = {}
            self._provider_snapshot_refreshed_at = provider_snapshot_refreshed_at
        for timing in provider_timings or []:
            key = str(timing.get("key", ""))
            if not key or timing.get("reused_recent"):
                continue
            if (
                timing.get("cancelled")
                or timing.get("deferred")
                or timing.get("update_error")
                or timing.get("inventory_error")
            ):
                provider_snapshot_refreshed_at.pop(key, None)
                continue
            observed_end = float(timing.get("observation_finished_monotonic", 0.0))
            if observed_end > 0:
                provider_snapshot_refreshed_at[key] = observed_end
            else:
                provider_snapshot_refreshed_at.pop(key, None)
            duration = float(timing.get("duration_seconds", 0.0))
            if not key or duration < 0:
                continue
            previous = self._provider_duration_hints.get(key)
            self._provider_duration_hints[key] = (
                duration if previous is None else previous * 0.35 + duration * 0.65
            )
        for key in unavailable_provider_keys:
            provider_snapshot_refreshed_at.pop(key, None)
        for key in set(provider_snapshot_refreshed_at).difference(
            scheduled_timing_provider_keys
        ):
            # This also drops an optional provider that disappeared from PATH;
            # if it reappears, its first subsequent scan must be real.
            provider_snapshot_refreshed_at.pop(key, None)
        self.settings.data["provider_duration_hints"] = {
            key: round(value, 3)
            for key, value in self._provider_duration_hints.items()
            if key in self.providers and 0.0 <= value <= 600.0
        }
        if self._active_scan_owns_busy:
            self.progress.stop()
            self.progress.configure(mode="determinate")
            self._set_progress_value(0, animate=False)
        if not started_during_update:
            self._selection_touched_keys.clear()
        finish_checkpoint("provider_state")
        previous_updates = list(self._scan_view_items[False].values())
        previous_packages = list(self._scan_view_items[True].values())
        had_previous_scan = self._last_scan_completed_at is not None
        previous_items = {
            key: item for view in self._scan_view_items.values() for key, item in view.items()
        }
        previous_items.update(self.items)
        joint_inventory_keys = self._scan_expected_provider_keys.intersection(
            {WingetProvider.key, MICROSOFT_STORE_PROVIDER_KEY}
        )
        stale_provider_keys = self._scan_expected_provider_keys.difference(
            self._scan_current_provider_keys
        )
        if not joint_inventory_keys.issubset(self._scan_current_provider_keys):
            # Store and WinGet overlap. If either inventory failed, retain their
            # previous reconciled pair rather than combining fresh and stale evidence.
            stale_provider_keys.update(joint_inventory_keys)
        retained_stale_packages = [
            dataclasses.replace(item)
            for item in previous_packages
            if item.provider in stale_provider_keys
            and item.provider != PORTABLE_PROVIDER_KEY
        ]
        found_updates = stable_identity_instances(
            deduplicate_microsoft_store_inventory(found_updates)
        )
        found_packages = stable_identity_instances(
            deduplicate_microsoft_store_inventory(
                [item for item in found_packages if item.provider not in stale_provider_keys]
            )
        )
        package_dates = getattr(self, "_scan_windows_package_dates", {})
        apply_windows_package_dates(found_updates, package_dates)
        date_count = apply_windows_package_dates(found_packages, package_dates)
        reuse_cached_service_dates(found_packages, self._observation_inventory_snapshot.items)
        reuse_cached_service_dates(found_updates, self._observation_inventory_snapshot.items)
        self.logger.event(
            "windows_package_dates_reused",
            scan_generation=generation,
            available=len(package_dates),
            applied=date_count,
            source="same-scan-native-inventory",
        )
        apply_known_product_variant_names(found_updates)
        apply_known_product_variant_names(found_packages)
        observation_update_items = tuple(
            dataclasses.replace(item) for item in found_updates
        )
        finish_checkpoint("inventory_identity")
        original_restart_pending = dict(
            self.settings.data.get("restart_pending", {})
        )
        original_attempt_holds = dict(self.settings.data.get("attempt_holds", {}))
        original_package_history = dict(
            self.settings.data.get("package_history", {})
        )
        restart_reconciliation = reconcile_restart_pending_markers(
            self.settings.data,
            found_updates,
            refreshed_update_provider_keys,
        )
        if restart_reconciliation["changed"]:
            try:
                self.settings.save()
            except OSError as exc:
                self.settings.data["restart_pending"] = original_restart_pending
                self.settings.data["attempt_holds"] = original_attempt_holds
                self.settings.data["package_history"] = original_package_history
                self._append_log(
                    f"Could not save post-restart verification state: {exc}"
                )
            self.logger.event(
                "restart_pending_reconciled",
                scan_generation=generation,
                refreshed_provider_keys=sorted(refreshed_update_provider_keys),
                **restart_reconciliation,
            )
        finish_checkpoint("restart_state")
        inventory_icon_evidence = {
            (
                item.provider.casefold(),
                item.package_id.casefold(),
                item.current.casefold(),
                item.scope.casefold(),
            ): item
            for item in found_packages
            if item.icon_source
        }
        for item in found_updates:
            if item.icon_source:
                continue
            evidence = inventory_icon_evidence.get(
                (
                    item.provider.casefold(),
                    item.package_id.casefold(),
                    item.current.casefold(),
                    item.scope.casefold(),
                )
            )
            if evidence is not None:
                item.icon_source = evidence.icon_source
                item.metadata_sources = evidence.metadata_sources
                item.metadata_confidence = evidence.metadata_confidence
        finish_checkpoint("icon_evidence")
        update_items = [
            (
                item
                if item.provider in recent_snapshot_provider_keys
                else self._mark_item_enrichment_pending(item)
            )
            for item in apply_stored_selection_policy(found_updates, self.settings.data)
        ]
        package_items = apply_stored_selection_policy(found_packages, self.settings.data)
        package_items.extend(retained_stale_packages)
        cached_portable_records = self.portable_inventory.records()
        cached_portable_items = [
            portable_record_to_item(record) for record in cached_portable_records
        ]
        portable_update_items = apply_stored_selection_policy(
            [
                advisory
                for record in cached_portable_records
                if (advisory := portable_record_to_update_item(record)) is not None
            ],
            self.settings.data,
        )
        update_items.extend(portable_update_items)
        package_items.extend(cached_portable_items)
        post_update_unverified_providers = verification_failed_provider_keys
        if (
            self._active_scan_origin == "post-update-verification"
            and self._verification_results
            and post_update_unverified_providers
        ):
            current_update_keys = {item.key for item in update_items}
            update_items.extend(
                dataclasses.replace(
                    item,
                    selected=False,
                    status="Verification inconclusive — provider scan failed",
                )
                for item in previous_updates
                if item.key in self._verification_results
                and item.provider in post_update_unverified_providers
                and item.key not in current_update_keys
            )
        retain_active_rows = bool(self._active_operation_items) and (
            self._active_scan_origin != "post-update-verification"
        )
        if retain_active_rows:
            update_items, package_items = overlay_active_update_state(
                update_items,
                package_items,
                self._active_operation_items,
                list(self._active_operation_results),
                retain_missing_updates=True,
            )
        self._last_scan_delta = (
            update_scan_delta(previous_updates, update_items) if had_previous_scan else {}
        )
        finish_checkpoint("selection_and_portables")
        self._last_scan_duration_seconds = max(0.0, scan_duration_seconds)
        all_new_items = [*update_items, *package_items]
        retained_icon_keys = {
            item.key
            for item in all_new_items
            if (previous := previous_items.get(item.key)) is not None
            and item_icon_identity(previous) == item_icon_identity(item)
            and previous.current == item.current
            and item.key not in (changed_icon_keys or ())
        }
        if self._icon_catalog_loaded:
            retained_icon_keys.update(self._apply_icon_catalog_to_items(all_new_items))
        self._item_icon_source_cache = {
            key: source
            for key, source in self._item_icon_source_cache.items()
            if key in retained_icon_keys
        }
        self._package_icon_images = {
            memory_key: image
            for memory_key, image in self._package_icon_images.items()
            if memory_key[0] in retained_icon_keys
        }
        self._package_icon_misses = {
            memory_key
            for memory_key in self._package_icon_misses
            if memory_key[0] in retained_icon_keys
        }
        self._package_icon_ready = {
            memory_key
            for memory_key in self._package_icon_ready
            if memory_key[0] in retained_icon_keys
        }
        hold_summary = attempt_hold_scan_summary(
            self.settings.data, {item.candidate_key for item in update_items}
        )
        finish_checkpoint("icon_cache_retention")
        self._scan_view_items = {
            False: {item.key: item for item in update_items},
            True: {item.key: item for item in package_items},
        }
        self._last_scan_completed_at = dt.datetime.now().astimezone()
        self._provisional_inventory_keys = {
            item.key
            for item in package_items
            if item.provider in stale_provider_keys
            and item.provider != PORTABLE_PROVIDER_KEY
        }
        self.items = self._scan_view_items[self._last_scan_all_packages]
        self._show_scan_view(self._last_scan_all_packages, force=True,
                             retained_icon_keys=retained_icon_keys)
        finish_checkpoint("model_and_view_publish")
        selected_count = sum(item.selected for item in update_items)
        admin_count = sum(item.requires_admin for item in update_items)
        active_holds = int(hold_summary["active_count"])
        stale_holds = int(hold_summary["stale_count"])
        if errors:
            error_count = len(errors)
            error_fragment = (
                f"; {error_count} provider "
                f"{'error' if error_count == 1 else 'errors'}"
            )
        else:
            error_fragment = ""
        unavailable_fragment = (
            f"; {len(unavailable_provider_keys)} enabled provider(s) unavailable"
            if unavailable_provider_keys
            else ""
        )
        scan_result_label = (
            "Scan stopped with partial results"
            if scan_cancelled
            else "Concurrent scan complete"
            if deferred_provider_keys
            else "Scan complete"
        )
        completed_provider_count = max(
            0,
            provider_count - len(cancelled_provider_keys or ()),
        )
        provider_fragment = (
            f"{completed_provider_count}/{provider_count} providers"
            if scan_cancelled
            else f"{provider_count - len(deferred_provider_keys)} refreshed + "
            f"{len(deferred_provider_keys)} retained"
            if deferred_provider_keys
            else f"{provider_count - len(recent_snapshot_provider_keys)} refreshed + "
            f"{len(recent_snapshot_provider_keys)} recent snapshots retained"
            if recent_snapshot_provider_keys
            else f"{provider_count} providers"
        )
        self._append_log(
            f"{scan_result_label}: {len(update_items)} updates; {len(package_items)} packages "
            f"from {provider_fragment} in {scan_duration_seconds:.1f}s{error_fragment}"
            f"{unavailable_fragment}"
            + (
                f"; {len(cached_portable_items)} cached portable app(s)"
                if cached_portable_items
                else ""
            )
        )
        if started_during_update:
            self._append_log(
                "Concurrent scan refreshed available package managers without interrupting "
                "the update queue; active providers kept their previous catalog until final "
                "verification"
            )
        if active_holds or stale_holds:
            self._append_log(
                f"Attempt holds: {active_holds} active, {stale_holds} stale "
                "(read-only diagnostic history)",
                show_in_ui=False,
            )
        installed_date_sources = Counter(
            item.installed_date_source or "unavailable" for item in package_items
        )
        self.logger.event(
            "scan_finished",
            provider_count=provider_count,
            scan_mode="combined",
            scan_origin=self._active_scan_origin,
            started_during_update=started_during_update,
            visible_update_count=len(update_items),
            installed_package_count=len(package_items),
            cached_portable_count=len(cached_portable_items),
            portable_update_advisory_count=len(portable_update_items),
            selected_count=selected_count,
            privileged_count=admin_count,
            installed_date_coverage={
                "exact": sum(
                    bool(item.installed_date) and not item.installed_date_is_estimate
                    for item in package_items
                ),
                "approximate": sum(
                    bool(item.installed_date) and item.installed_date_is_estimate
                    for item in package_items
                ),
                "unavailable": sum(not item.installed_date for item in package_items),
                "sources": dict(installed_date_sources),
            },
            duration_seconds=scan_duration_seconds,
            provider_timings=provider_timings or [],
            attempt_holds=hold_summary,
            errors=errors,
            unavailable_providers=sorted(unavailable_provider_keys),
            stopped=scan_cancelled,
            skipped_providers=sorted(cancelled_provider_keys or ()),
            deferred_providers=sorted(deferred_provider_keys),
            recent_snapshot_providers=sorted(recent_snapshot_provider_keys),
            recent_snapshot_grace_seconds=POST_UPDATE_PROVIDER_REUSE_GRACE_SECONDS,
            update_items=[item_diagnostic_fields(item) for item in update_items],
            **(
                {"installed_items": [item_diagnostic_fields(item) for item in package_items]}
                if self.debug_mode
                else {}
            ),
        )
        for item in update_items:
            if item.provider == "winget" and item.applicability_prediction != PREDICTION_ORDINARY:
                self.logger.event(
                    "preflight_decision",
                    candidate_key=item.candidate_key,
                    item=item_diagnostic_fields(item),
                    predicted_outcome=item.applicability_prediction,
                    predicted_hresult=item.predicted_hresult,
                    confidence=item.prediction_confidence,
                    source=item.prediction_source,
                    reasons=list(item.prediction_reasons),
                    evidence={
                        "installed": {
                            "scope": item.installed_for,
                            "technology": item.installed_technology,
                            "location": item.installed_location,
                            "product_codes": list(item.product_codes),
                        },
                        "available": {
                            "technology": item.available_technology,
                            "scope": item.available_scope,
                            "upgrade_behavior": item.available_upgrade_behavior,
                        },
                    },
                )
        finish_checkpoint("diagnostic_logging")
        history_before_verification = self.settings.data.get("package_history", {})
        if not scan_cancelled and not started_during_update:
            self._verify_pending_uninstalls(found_packages, {
                str(timing.get("key", "")) for timing in provider_timings or []
                if not any(timing.get(field) for field in
                           ("cancelled", "deferred", "reused_recent", "reused_previous", "inventory_error"))
            })
        if not scan_cancelled and not started_during_update:
            self._confirm_pending_suggested_install_history(found_packages)
        if (
            self._verification_results
            and self._active_scan_origin == "post-update-verification"
            and not started_during_update
        ):
            self._finish_post_update_verification(
                verification_failed_provider_keys,
                unavailable_attempted_provider_keys,
            )
        if (
            self._last_scan_all_packages
            and self.settings.data.get("package_history", {}) != history_before_verification
        ):
            # This view was published before verification saved its history.
            # Refresh the date cells (and date ordering) without another scan.
            self._schedule_rebuild_tree(prime_cached_first_paint=True)
        current_scan_settings = {
            "providers": dict(self.settings.data["providers"]),
            "auto_elevate": bool(self.settings.data.get("auto_elevate", True)),
        }
        settings_changed_during_scan = (
            bool(self._active_scan_settings_snapshot)
            and current_scan_settings != self._active_scan_settings_snapshot
        )
        inventory_incomplete_provider_keys = self._scan_expected_provider_keys.difference(
            self._scan_current_provider_keys
        )
        if scan_cancelled:
            self._mark_scan_refresh_needed(
                "Scan stopped before every provider completed; run Scan again for current results"
            )
        elif errors or failed_provider_keys:
            self._mark_scan_refresh_needed(
                "Last scan completed with provider errors; rescan after fixing the provider"
            )
        elif unavailable_provider_keys:
            labels = ", ".join(
                self.providers[key].label if key in self.providers else key
                for key in sorted(unavailable_provider_keys)
            )
            self._mark_scan_refresh_needed(
                f"Scan incomplete because enabled provider coverage was unavailable: {labels}"
            )
        elif inventory_incomplete_provider_keys:
            labels = ", ".join(
                self.providers[key].label if key in self.providers else key
                for key in sorted(inventory_incomplete_provider_keys)
            )
            self._mark_scan_refresh_needed(
                f"Installed inventory remains provisional for providers that did not run: "
                f"{labels}"
            )
        elif settings_changed_during_scan:
            self._mark_scan_refresh_needed(
                "Provider or elevation choices changed during the scan; rescan to apply them"
            )
        elif started_during_update:
            self._mark_scan_refresh_needed(
                "This scan overlapped an update batch; live results are shown, and a final "
                "verification scan will confirm the settled package state"
            )
        else:
            self._mark_scan_current()
            self._provisional_inventory_keys.clear()
            self._provisional_inventory_scanned_at = None
            provider_scanned_at = {
                key: value
                for key, value in self._observation_inventory_snapshot.provider_scanned_at.items()
                if key in self._scan_expected_provider_keys
            }
            provider_started_at = {
                key: value
                for key, value in self._observation_inventory_snapshot.provider_started_at.items()
                if key in self._scan_expected_provider_keys
            }
            observation_timings = {
                str(timing.get("key", "")): timing for timing in provider_timings or []
            }
            completed_at_iso = datetime_storage_timestamp(self._last_scan_completed_at)
            for key in self._scan_expected_provider_keys - recent_snapshot_provider_keys:
                timing = observation_timings.get(key, {})
                provider_scanned_at[key] = str(timing.get("observation_finished_at") or completed_at_iso)
                started_at = str(timing.get("observation_started_at", ""))
                if started_at:
                    provider_started_at[key] = started_at
                else:
                    provider_started_at.pop(key, None)
            for key in recent_snapshot_provider_keys:
                provider_scanned_at.setdefault(key, completed_at_iso)
            self._remember_confirmed_history_absences(
                found_packages,
                self._scan_current_provider_keys - recent_snapshot_provider_keys,
                provider_started_at,
            )
            self._update_release_observations = evolve_update_observations(
                self._observation_inventory_snapshot,
                observation_update_items,
                self._scan_expected_provider_keys,
                self._last_scan_completed_at,
                provider_scanned_at,
            )
            nonportable_packages = tuple(
                dataclasses.replace(item)
                for item in package_items
                if item.provider != PORTABLE_PROVIDER_KEY
            )
            fresh_inventory_provider_keys = (
                self._scan_expected_provider_keys - recent_snapshot_provider_keys
            )
            previous_installation_observations = self._installation_observations
            self._installation_observations = evolve_installation_observations(
                self._observation_inventory_snapshot,
                nonportable_packages,
                self._scan_expected_provider_keys,
                fresh_inventory_provider_keys,
                provider_scanned_at,
            )
            if self._installation_observations != previous_installation_observations:
                self._schedule_rebuild_tree()
            self._observation_inventory_snapshot = InstalledInventorySnapshot(
                nonportable_packages,
                frozenset(self._scan_expected_provider_keys),
                self._last_scan_completed_at,
                self._update_release_observations,
                provider_scanned_at,
                self._installation_observations,
                provider_started_at,
            )
            self._write_installed_inventory_cache_async(
                self._observation_inventory_snapshot,
                generation,
            )
        finish_checkpoint("history_and_persistence")
        if (
            not self._last_scan_all_packages
            and not self.items
            and not errors
            and not failed_provider_keys
            and not unavailable_provider_keys
            and not inventory_incomplete_provider_keys
            and not settings_changed_during_scan
            and not started_during_update
            and not scan_cancelled
        ):
            checked_time = self._last_scan_completed_at or dt.datetime.now().astimezone()
            checked_short = clock_display_time(checked_time, twelve_hour=True)
            self._empty_state_message = f"✓ Everything is up to date\nChecked {checked_short}"
        else:
            self._empty_state_message = ""
        if unavailable_provider_keys:
            labels = ", ".join(
                self.providers[key].label if key in self.providers else key
                for key in sorted(unavailable_provider_keys)
            )
            self._notify_user(
                "The scan is incomplete because enabled provider coverage was unavailable: "
                f"{labels}. Review Toolchain Health and the Activity log before trusting a "
                "zero-update result.",
                level="warning",
                summary=f"Incomplete scan — unavailable provider coverage: {labels}",
            )
        self._update_empty_state()
        scan_owned_busy = self._active_scan_owns_busy
        update_still_running = self.busy and self._busy_kind == "update"
        self._scan_active = False
        self._active_scan_owns_busy = False
        self._scan_cancel_requested.clear()
        if scan_owned_busy and self.busy and self._busy_kind == "scan":
            self._set_busy(False)
        else:
            self._refresh_scan_button_style()
        self._refresh_scan_summary_counts()
        if started_during_update and not update_still_running:
            self._active_operation_items.clear()
            self._active_operation_results.clear()
        if not scan_cancelled and not started_during_update:
            self._start_winget_enrichment()
            self._request_portable_local_refresh()
            self._apply_pending_retry_selection()
        self._schedule_idle_date_sleuth()
        finish_checkpoint("final_ui_and_followups")
        self._last_finish_scan_stage_ms = finish_stages

    def _build_package_list_drag(self) -> None:
        """Intercept dragging only in All packages; keep native click bindings."""
        self._package_list_drag: dict[str, Any] | None = None
        self._package_list_motion_after_id: str | None = None
        self._package_list_drag_after_id: str | None = None
        self._package_list_edge = ""
        self._package_list_edge_offset = 0
        self._package_list_edge_header = None
        self._package_list_edge_cover = None
        tag = f"wdp-list-drag-{id(self.tree)}"
        self.tree.bindtags((tag, *self.tree.bindtags()))
        self.tree.bind_class(tag, "<Button-1>", self._package_list_press)
        self.tree.bind_class(tag, "<B1-Motion>", self._package_list_drag_move)
        self.tree.bind_class(tag, "<ButtonRelease-1>", self._package_list_release)
        self.tree.bind_class(tag, "<MouseWheel>", self._package_list_wheel_feedback)
        for sequence in ("<Double-Button-1>", "<Button-3>", "<KeyPress>",
                         "<FocusOut>", "<Unmap>"):
            self.tree.bind_class(tag, sequence, self._cancel_package_list_gesture)
        self._package_list_viewport.bind("<Configure>", self._cancel_package_list_gesture)
        self._package_list_viewport.bind("<Button-1>", self._cancel_package_list_gesture)
        with contextlib.suppress(self.tk.TclError):
            self.tree.bind_class(tag, "<TouchpadScroll>", lambda _event: self._stop_package_list_motion())
        for scrollbar in self._package_list_widgets[1:]:
            scrollbar.bind("<Button-1>", lambda _event: self._stop_package_list_motion(), add="+")

    def _package_list_wheel_feedback(self, event: Any) -> None:
        self._stop_package_list_motion()
        if (self._closing or not self._last_scan_all_packages or self._package_gallery_mode
                or not event.delta or event.state & (0x0001 | 0x0004 | 0x0008 | 0x20000)):
            return
        # Observe the result after Tk's ordinary wheel binding has scrolled rows.
        self._package_list_motion_after_id = self.root.after_idle(
            self._package_list_wheel_edge, 1 if event.delta < 0 else -1)

    def _package_list_wheel_edge(self, direction: int) -> None:
        self._package_list_motion_after_id = None
        if (self._closing or not self._last_scan_all_packages or self._package_gallery_mode
                or self._native_window_interaction_active()):
            return
        first, last = self.tree.yview()
        edge = "top" if direction < 0 and first <= 0 else "bottom" if direction > 0 and last >= 1 else ""
        if edge and self.items:
            self._start_package_list_edge_return(edge, pulse=True)

    def _cancel_package_list_gesture(self, event: Any) -> str | None:
        self._stop_package_list_motion()
        return None

    def _clear_package_list_edge(self) -> None:
        if not getattr(self, "_package_list_edge", ""):
            return
        self._package_list_edge = ""
        self._package_list_edge_offset = 0
        self.tree.place_configure(y=0)
        if self._package_list_edge_header is not None:
            self._package_list_edge_header.place_forget()
            self._package_list_edge_cover.place_forget()

    def _forward_package_list_header(self, event: Any, sequence: str) -> str:
        heading_click = event.y < self._package_list_edge_header_height
        self._stop_package_list_motion()
        if heading_click:
            options = dict(x=event.x, y=event.y, state=event.state, time=getattr(event, "time", 0))
            if sequence == "<MouseWheel>":
                options["delta"] = event.delta
            self.tree.event_generate(sequence, **options)
        return "break"

    def _show_package_list_edge(self, edge: str, pixels: float) -> None:
        """Translate the clipped list body; a native heading cover stays stationary."""
        row_height = max(1, self.visuals.px(UPDATE_ROW_HEIGHT_DIP))
        offset = round(min(row_height * .75, max(0.0, pixels))) * (1 if edge == "top" else -1)
        if self._package_list_edge != edge:
            self._clear_package_list_edge()
            self._package_list_edge = edge
            self.tree.yview_moveto(0 if edge == "top" else 1)
            header = self._package_list_edge_header
            if header is None:
                self._package_list_edge_cover = self.tk.Frame(
                    self._package_list_viewport, borderwidth=0, highlightthickness=0)
                header = self._package_list_edge_header = self.ttk.Treeview(
                    self._package_list_edge_cover, height=0, takefocus=False)
                header.bindtags((str(header),))
                for sequence in ("<ButtonPress-1>", "<ButtonRelease-1>", "<ButtonPress-3>", "<MouseWheel>"):
                    header.bind(sequence, lambda event, seq=sequence: self._forward_package_list_header(event, seq))
            columns = self.tree.cget("columns")
            header.configure(columns=columns, displaycolumns=self.tree.cget("displaycolumns"),
                             show=self.tree.cget("show"), style=self.tree.cget("style"))
            for column in ("#0", *columns):
                config = self.tree.column(column)
                header.column(column, **{name: config[name] for name in ("width", "minwidth", "stretch", "anchor")})
                config = self.tree.heading(column)
                header.heading(column, **{name: config[name] for name in ("text", "image", "anchor")})
            header.xview_moveto(self.tree.xview()[0])
            # The real widget still owns column sizing, sorting and every package row.
            self._package_list_edge_header_height = next(
                (y for y in range(1, row_height * 3)
                 if self.tree.identify_region(self.visuals.px(8), y) in {"tree", "cell"}), row_height)
        self._package_list_edge_offset = offset
        self.tree.place_configure(y=offset)
        header = self._package_list_edge_header
        cover_height = self._package_list_edge_header_height + max(0, offset)
        self._package_list_edge_cover.place(x=0, y=0, relwidth=1, height=cover_height)
        # Keep the native field's bottom border below the clip, so it cannot
        # appear as a moving separator across the temporary pull space.
        header.place(x=0, y=0, relwidth=1, height=cover_height + row_height)
        header.xview_moveto(self.tree.xview()[0])
        self._package_list_edge_cover.lift()

    def _start_package_list_edge_return(self, edge: str, *, pulse: bool = False) -> None:
        self._cancel_after_id("_package_list_motion_after_id")
        amplitude = (self.visuals.px(UPDATE_ROW_HEIGHT_DIP) * .6 if pulse
                     else abs(self._package_list_edge_offset))
        state = dict(edge=edge, start=time.monotonic(), amplitude=amplitude, pulse=pulse)
        self._show_package_list_edge(edge, 0 if pulse else amplitude)
        self._package_list_motion_after_id = self.root.after(16, self._animate_package_list_edge, state)

    def _animate_package_list_edge(self, state: dict[str, Any]) -> None:
        self._package_list_motion_after_id = None
        if (self._closing or not self._last_scan_all_packages or self._package_gallery_mode
                or self._native_window_interaction_active()):
            self._stop_package_list_motion()
            return
        progress = min(1.0, max(0.0, (time.monotonic() - state["start"]) / .24))
        if progress >= 1:
            self._stop_package_list_motion()
            return
        factor = math.sin(math.pi * progress) if state["pulse"] else (1 - progress) ** 3
        self._show_package_list_edge(state["edge"], state["amplitude"] * factor)
        self._package_list_motion_after_id = self.root.after(16, self._animate_package_list_edge, state)

    def _stop_package_list_motion(self) -> None:
        active = (getattr(self, "_package_list_drag", None) is not None
                  or getattr(self, "_package_list_motion_after_id", None) is not None
                  or bool(getattr(self, "_package_list_edge", "")))
        self._cancel_after_id("_package_list_drag_after_id")
        self._cancel_after_id("_package_list_motion_after_id")
        self._package_list_drag = None
        self._clear_package_list_edge()
        if active and hasattr(self, "tree"):
            with contextlib.suppress(self.tk.TclError):
                self.tree.configure(cursor="")
            self._icon_scroll_quiet_until = 0.0
            if not self._closing:
                self._note_icon_idle_activity()
                self._schedule_visible_icon_hydration(delay_ms=0, restart=True)

    def _package_list_press(self, event: Any) -> str | None:
        self._stop_package_list_motion()
        if (not self._last_scan_all_packages or self._package_gallery_mode or self._closing
                or event.state & (0x0001 | 0x0004 | 0x0008 | 0x20000)
                or self.tree.identify_region(event.x, event.y) not in {"tree", "cell"}):
            return
        if self._tree_display_column_name(self.tree.identify_column(event.x)) == "selected":
            return
        key = self.tree.identify_row(event.y)
        if key not in self.items:
            return
        bounds = self.tree.bbox(key)
        row_height = bounds[3] if bounds else max(1, self.visuals.px(UPDATE_ROW_HEIGHT_DIP))
        count = len(getattr(self, "_tree_display_order", ()) or self.tree.get_children())
        first, last = self.tree.yview()
        top = round(first * count) * row_height
        pointer_y = getattr(event, "y_root", event.y)
        self._package_list_drag = dict(
            x=event.x, y=pointer_y, last_y=pointer_y, active=False, top=float(top),
            maximum=max(0, round(count * (1 - last + first))) * row_height,
            row_height=row_height, count=count,
            samples=deque([(time.monotonic(), float(top))], maxlen=32))

    def _package_list_drag_move(self, event: Any) -> str | None:
        drag = getattr(self, "_package_list_drag", None)
        if drag is None:
            return None
        pointer_y = getattr(event, "y_root", event.y)
        delta = drag["last_y"] - pointer_y
        drag["last_y"] = pointer_y
        if not drag["active"]:
            if max(abs(event.x - drag["x"]), abs(pointer_y - drag["y"])) < self.visuals.px(6):
                return "break"
            drag["active"] = True
            self._tree_leave()
            self.tree.configure(cursor="hand2")
            delta = drag["y"] - pointer_y
        overshoot = drag.get("edge_pull", 0) * (-1 if drag.get("edge") == "top" else 1)
        requested = drag["top"] + overshoot + delta
        edge = "top" if requested < 0 else "bottom" if requested > drag["maximum"] else ""
        drag["edge_pull"] = -requested if edge == "top" else requested - drag["maximum"] if edge else 0
        drag["edge"] = edge
        drag["top"] = max(0.0, min(float(drag["maximum"]), requested))
        now = time.monotonic()
        samples = drag["samples"]
        sample = (now, drag["top"])
        if len(samples) > 1 and int(now / .008) == int(samples[-1][0] / .008):
            samples[-1] = sample
        else:
            samples.append(sample)
        while len(samples) > 2 and samples[0][0] < now - .12:
            samples.popleft()
        self._icon_scroll_quiet_until = now + .32
        if self._package_list_drag_after_id is None:
            self._package_list_drag_after_id = self.root.after(8, self._flush_package_list_drag)
        return "break"

    def _flush_package_list_drag(self) -> None:
        self._cancel_after_id("_package_list_drag_after_id")
        if (self._closing or not self._last_scan_all_packages or self._package_gallery_mode
                or self._native_window_interaction_active()):
            self._stop_package_list_motion()
            return
        if (drag := self._package_list_drag) is not None and drag["active"]:
            if drag.get("edge"):
                pull, row = drag["edge_pull"], drag["row_height"]
                self._show_package_list_edge(drag["edge"], row * .75 * pull / (row + pull))
                return
            self._clear_package_list_edge()
            self._scroll_package_list_position(drag)

    def _scroll_package_list_position(self, state: dict[str, Any]) -> None:
        row = round(state["top"] / state["row_height"])
        if row != round(self.tree.yview()[0] * state["count"]):
            self.tree.yview_moveto(row / max(1, state["count"]))

    def _package_list_release(self, event: Any) -> str | None:
        drag = self._package_list_drag
        if drag is None:
            return None
        if getattr(event, "y_root", event.y) != drag["last_y"]:
            self._package_list_drag_move(event)
        self._flush_package_list_drag()
        if self._package_list_drag is not drag:
            return "break"
        self._package_list_drag = None
        self.tree.configure(cursor="")
        if not drag["active"]:
            return None
        if self._package_list_edge:
            self._start_package_list_edge_return(self._package_list_edge)
            return "break"
        now = time.monotonic()
        samples = drag["samples"]
        paused = now - samples[-1][0] > .10
        samples.append((now, drag["top"]))
        while len(samples) > 2 and samples[0][0] < now - .12:
            samples.popleft()
        elapsed = now - samples[0][0]
        velocity = ((drag["top"] - samples[0][1]) / elapsed
                    if elapsed >= .01 and not paused else 0.0)
        limit = self.visuals.px(3600)
        drag["velocity"] = max(-limit, min(limit, velocity))
        drag["time"] = now
        drag["deadline"] = now + .016
        if abs(drag["velocity"]) >= self.visuals.px(80):
            self._package_list_motion_after_id = self.root.after(16, self._coast_package_list, drag)
        else:
            self._icon_scroll_quiet_until = 0.0
            self._schedule_visible_icon_hydration(delay_ms=0, restart=True)
        return "break"

    def _coast_package_list(self, state: dict[str, Any]) -> None:
        if (self._closing or not self._last_scan_all_packages or self._package_gallery_mode
                or self._native_window_interaction_active()):
            self._stop_package_list_motion()
            return
        now = time.monotonic()
        elapsed = max(0.0, now - state["time"])
        if elapsed > .12:
            self._stop_package_list_motion()
            return
        state["time"] = now
        decay = math.exp(-elapsed / .30)
        state["top"] = max(0.0, min(state["maximum"], state["top"] + state["velocity"] * .30 * (1 - decay)))
        state["velocity"] *= decay
        self._scroll_package_list_position(state)
        if not 0 < state["top"] < state["maximum"]:
            self._start_package_list_edge_return("top" if state["top"] <= 0 else "bottom", pulse=True)
            return
        if abs(state["velocity"]) < self.visuals.px(12):
            self._stop_package_list_motion()
            return
        self._icon_scroll_quiet_until = now + .32
        finished = time.monotonic()
        deadline = state["deadline"] + .016
        if deadline <= finished:
            deadline += (math.floor((finished - deadline) / .016) + 1) * .016
        state["deadline"] = deadline
        self._package_list_motion_after_id = self.root.after(
            max(1, math.ceil((deadline - finished) * 1000)), self._coast_package_list, state)

    def _icon_speculation_paused(self) -> bool:
        """Keep optional preparation behind input, visible work and native gestures."""
        now = time.monotonic()
        return bool(
            getattr(self, "busy", False) or getattr(self, "_cache_clear_inflight", False)
            or self._native_window_interaction_active()
            or now < max(getattr(self, "_icon_scroll_quiet_until", 0.0),
                         getattr(self, "_details_idle_quiet_until", 0.0))
            or getattr(self, "_rebuild_after_id", None)
            or getattr(self, "_package_list_drag", None)
            or getattr(self, "_package_list_motion_after_id", None)
            or getattr(self, "_package_gallery_drag", None)
            or getattr(self, "_package_gallery_motion_after_id", None)
            or (getattr(self, "events", None) is not None and not self.events.empty())
        )

    def _note_icon_idle_activity(self, _event: Any = None) -> None:
        self._details_idle_quiet_until = time.monotonic() + ICON_IDLE_QUIET_MS / 1000.0
        self._enqueue_gallery_idle_promotions()

    def _enqueue_gallery_idle_promotions(self) -> None:
        if not hasattr(self, "_details_idle_queue"):
            return
        self._details_idle_plan_dirty = True
        if (self._closing or not self._last_scan_all_packages
                or not self.items):
            return
        if self._details_idle_after_id is None:
            self._details_idle_after_id = self.root.after(ICON_IDLE_QUIET_MS, self._request_details_idle_promotion)

    def _request_details_idle_promotion(self) -> None:
        self._details_idle_after_id = self.root.after_idle(self._pump_details_idle_prewarm)

    def _details_idle_vector_data(self, item: UpdateItem, size: int) -> bytes | None:
        style = fallback_vector_style(item)
        if ((style, size, self.palette["mode"]) in self._provider_icon_images
                or not (preferred_vector_style(item) or self._package_gallery_icon_missing(item))):
            return None
        path = self._details_idle_vector_paths.get((style, size))
        return getattr(self, "_icon_catalog_blobs", {}).get(path)

    def _resident_vector_icon_image(self, item: UpdateItem, size: int) -> Any | None:
        """Promote worker-prepared vector bytes; never render or read files here."""
        if not (preferred_vector_style(item) or self._package_gallery_icon_missing(item)):
            return None
        cache_key = (fallback_vector_style(item), size, self.palette["mode"])
        image = self._provider_icon_images.get(cache_key)
        if image is None and (data := self._details_idle_vector_data(item, size)):
            with contextlib.suppress(self.tk.TclError):
                image = self.tk.PhotoImage(data=data, format="png")
                image._windevpilot_source_png = data
                self._provider_icon_images[cache_key] = image
        return image

    def _details_idle_image(self, item: UpdateItem, size: int) -> Any | None:
        """Peek at final resident artwork without decoding or changing LRU order."""
        preferred = preferred_vector_style(item)
        if not preferred:
            image = self._details_icon_images.get((item.key, size, self.palette["mode"]))
            if image is not None:
                return image
        if preferred or self._package_gallery_icon_missing(item):
            return self._provider_icon_images.get((fallback_vector_style(item), size, self.palette["mode"]))
        return None

    def _details_idle_can_promote(self, item: UpdateItem, size: int) -> bool:
        image = self._details_idle_image(item, size)
        if image is not None:
            return self._compact_icon_if_resident(item) is None
        if preferred_vector_style(item):
            return self._details_idle_vector_data(item, size) is not None
        return (self._resident_details_icon_path(item, size) is not None
                or self._details_idle_vector_data(item, size) is not None)

    def _details_idle_target_keys(self, size: int) -> Sequence[str]:
        order = getattr(self, "_tree_display_order", None)
        if order is None:
            order = self.tree.get_children()
        widget = self._package_gallery_canvas if self._package_gallery_mode else self.tree
        width, height = max(1, widget.winfo_width()), max(1, widget.winfo_height())
        columns = max(1, width // max(1, self.visuals.px(132)))
        row_height = size + self.visuals.px(45)
        if self._package_gallery_mode:
            _keys, columns, _cell, row_height = self._package_gallery_geometry
            # Keep the existing page-ahead range; spare targets can prepare the
            # other size in retained rows too, without creating speculative tiles.
            top = max(0, widget.canvasy(0))
            first = max(0, int(top // row_height) - 1) * columns
            stop = min(len(order), (int((top + height) // row_height) + 2) * columns)
            count = min(ICON_IDLE_TARGET_LIMIT, 2 * math.ceil(height / row_height) * columns)
            forward = getattr(self, "_package_gallery_scroll_direction", 1) > 0
            if stop == len(order):
                forward = False
            elif first == 0:
                forward = True
            nearby = order[stop:stop + count] if forward else order[max(0, first - count):first][::-1]
            trail = (order[max(0, first - count // 4):first] if forward
                     else order[stop:stop + count // 4])
            return (*nearby, *order[first:stop], *trail)[:ICON_IDLE_TARGET_LIMIT]
        # The hidden canvas often measures 1x1; use the displayed table's viewport.
        count = min(ICON_IDLE_TARGET_LIMIT, 2 * columns * (int(height // row_height) + 2))
        keys = list(order[:count])
        focus = self.tree.focus()
        if focus in self.items and focus not in keys and len(keys) < ICON_IDLE_TARGET_LIMIT:
            keys.append(focus)
        return keys

    def _pump_details_idle_prewarm(self) -> None:
        self._details_idle_after_id = None
        if self._closing or not self._last_scan_all_packages:
            self._details_idle_queue.clear()
            return
        visible_work = self._package_gallery_mode and (
            self._package_gallery_after_id is not None or self._package_gallery_pending or any(
                key[0].startswith("details:package-gallery:") for key in self._icon_prepare_inflight))
        if self._icon_speculation_paused() or visible_work:
            self._details_idle_after_id = self.root.after(ICON_IDLE_QUIET_MS, self._request_details_idle_promotion)
            return
        size = max(48, self.visuals.px(DETAIL_ICON_SIZE_DIP))
        deadline = time.perf_counter() + ICON_IDLE_PROMOTION_TIME_BUDGET_SECONDS
        if self._details_idle_plan_dirty:
            self._details_idle_plan_dirty = False
            targets = [
                key for key in self._details_idle_target_keys(size)
                if (item := self.items.get(key)) is not None and self._details_idle_can_promote(item, size)]
            # Additional compact work must not delay normal-size lookahead.
            targets.sort(key=lambda key: self._details_idle_image(self.items[key], size) is not None)
            self._details_idle_queue = deque(targets)
        # A soft deadline includes planning and skips, and is checked between
        # individual image operations. Tk work cannot be interrupted mid-image.
        while self._details_idle_queue:
            item = self.items.get(self._details_idle_queue.popleft())
            if item is not None and self._details_idle_can_promote(item, size):
                self._promote_details_idle_item(item, size)
                if not self._package_gallery_mode:
                    break  # Preserve the list's one-image-per-turn policy.
            if time.perf_counter() >= deadline:
                break
        if self._details_idle_queue:
            self._details_idle_after_id = self.root.after(ICON_IDLE_PROMOTION_INTERVAL_MS, self._request_details_idle_promotion)

    def _promote_details_idle_item(self, item: UpdateItem, size: int) -> None:
        """Prepare one normal or compact image after the idle pump's guards."""
        # Never evict useful decoded art to make room for speculation. Include
        # shared vector photos in this conservative admission estimate as well.
        cache = self._details_icon_images
        provider_cache = self._provider_icon_images
        image = self._details_idle_image(item, size)
        compact_size = round(size * PACKAGE_GALLERY_COMPACT_SCALE)
        charge = cache.charge
        charge += sum(DecodedIconCache.entry_charge(key) for key in provider_cache)
        added_charge = 8 * (compact_size if image is not None else size) ** 2 + 1024
        if image is None and charge + added_charge > DETAIL_ICON_MEMORY_BUDGET_BYTES:
            self._details_idle_queue.clear()
            return
        if image is not None:
            self._package_gallery_compact_image(image, create=True, item=item)
        elif not preferred_vector_style(item) and self._resident_details_icon_path(item, size):
            self._details_icon_image_if_ready(item, size, resident_only=True)
        else:
            self._resident_vector_icon_image(item, size)
        # Finish normal lookahead before compact work. The pump checks its
        # deadline between stages and admission is checked for every image.
        if image is None and self._details_idle_image(item, size) is not None:
            self._details_idle_queue.append(item.key)

    def _admit_icon_blob(self, path: str, data: bytes) -> bool:
        """Admit already validated worker bytes without evicting resident artwork."""
        blobs = self._icon_catalog_blobs
        if (not data.startswith(PNG_SIGNATURE) or len(data) > ICON_CATALOG_SINGLE_BLOB_MAX_BYTES
                or sum(map(len, blobs.values())) - len(blobs.get(path, b"")) + len(data)
                > ICON_CATALOG_BLOB_BUDGET_BYTES):
            return False
        blobs[path] = data
        return True

    def _finish_vector_icon_resident(self, generation: int, style: str, size: int, path: str, data: bytes) -> None:
        if (self._closing or generation != self._icon_prepare_generation
                or size != max(48, self.visuals.px(DETAIL_ICON_SIZE_DIP))):
            return
        if self._admit_icon_blob(path, data):
            self._details_idle_vector_paths[(style, size)] = path
            self._enqueue_gallery_idle_promotions()

    def _build_package_gallery(self, parent: Any) -> None:
        self._package_gallery_compact = False
        self._package_gallery_prime_resident = False
        if not hasattr(self, "_compact_icon_images"):
            self._compact_icon_images = {}
            self._compact_icon_tokens = {}
        self._package_gallery_scaled_context = (self._icon_prepare_generation, max(48, self.visuals.px(DETAIL_ICON_SIZE_DIP)), self.palette["mode"])
        self._package_gallery_zoom_anchor: int | None = None
        self._package_gallery_zoom_time = float("-inf")
        self._package_gallery_fitted_names: OrderedDict[tuple[Any, ...], str] = OrderedDict()
        self._details_idle_queue: deque[str] = deque()
        self._details_idle_after_id: str | None = None
        self._details_idle_plan_dirty = False
        self._details_idle_quiet_until = 0.0
        self._details_idle_vector_paths: dict[tuple[str, int], str] = {}
        self._package_gallery_scroll_fraction = 0.0
        self._package_gallery_scroll_direction = 1
        for event in ("<KeyPress>", "<ButtonPress>", "<MouseWheel>", "<B1-Motion>"):
            self.root.bind(event, self._note_icon_idle_activity, add="+")
        self.tree.bind("<Configure>", self._note_icon_idle_activity, add="+")
        self._package_gallery_geometry = ((), 1, 1, 1)
        self._package_gallery_viewport_keys: set[str] = set()
        self._package_gallery_misses: dict[str, tuple[GalleryIconToken, float]] = {}
        self._package_gallery_drag: dict[str, Any] | None = None
        self._package_gallery_motion_after_id: str | None = None
        self._package_gallery_drag_after_id: str | None = None
        self._package_gallery_velocity = 0.0
        self._package_gallery_elastic = False
        self._package_gallery_side_offset = 0
        self._package_gallery_side_return: tuple[float, float] | None = None
        # Logical destination and bounded elastic aim; wheel input spends a fixed
        # distance rather than adding a second, velocity-based fling afterward.
        self._package_gallery_wheel_target: tuple[float, float] | None = None
        self._package_gallery_bounce_state: tuple[float, float, float, float] | None = None
        self._package_gallery_labels: dict[str, int] = {}
        self._package_gallery_layouts: dict[str, tuple[Any, ...]] = {}
        self._package_gallery_focus_id: int | None = None
        self._package_gallery_frame = self.ttk.Frame(parent)
        self._package_gallery_frame.columnconfigure(0, weight=1)
        self._package_gallery_frame.rowconfigure(0, weight=1)
        self._package_gallery_canvas = self.tk.Canvas(
            self._package_gallery_frame, background=self.palette["surface"],
            highlightthickness=0, borderwidth=0, takefocus=True,
        )
        canvas = self._package_gallery_canvas
        self._register_theme_widget(canvas, background="surface")
        def scrollbar_command(*args: Any) -> None:
            self._stop_package_gallery_motion()
            if len(args) == 3 and args[0] == "scroll" and args[2] == "units":
                args = ("scroll", round(float(args[1]) * max(1, self.visuals.px(24))), "units")
            canvas.yview(*args)

        scrollbar = self.ttk.Scrollbar(
            self._package_gallery_frame, orient="vertical", command=scrollbar_command,
        )

        def scrolled(first: str, last: str) -> None:
            scrollbar.set(first, last)
            fraction = float(first)
            if abs(fraction - self._package_gallery_scroll_fraction) > 1e-9:
                self._package_gallery_scroll_direction = 1 if fraction > self._package_gallery_scroll_fraction else -1
            self._package_gallery_scroll_fraction = fraction
            self._note_icon_idle_activity()
            self._schedule_package_gallery_render()

        canvas.configure(yscrollcommand=scrolled)
        canvas.grid(row=0, column=0, sticky="nsew")
        scrollbar.grid(row=0, column=1, sticky="ns")
        canvas.bind("<Configure>", lambda _event: self._schedule_package_gallery_render())
        canvas.bind("<MouseWheel>", self._package_gallery_wheel)
        canvas.bind("<Control-MouseWheel>", self._package_gallery_zoom)
        canvas.bind("<Button-1>", self._package_gallery_press)
        canvas.bind("<Double-Button-1>", self._package_gallery_double_click)
        canvas.bind("<B1-Motion>", self._package_gallery_drag_move)
        canvas.bind("<ButtonRelease-1>", self._package_gallery_release)
        canvas.bind("<FocusOut>", lambda _event: self._stop_package_gallery_motion())
        canvas.bind("<Button-3>", self._package_gallery_context_menu)
        for key in ("Left", "Right", "Up", "Down", "Prior", "Next", "Home", "End", "Return", "Escape"):
            canvas.bind(f"<KeyPress-{key}>", self._package_gallery_key)
        canvas.bind("<Control-Return>", self._run_from_keyboard)

    def _capture_view_preferences(self) -> None:
        if not self.settings.data.get("preserve_settings", False):
            self.settings.data["view_preferences"] = {}
            return
        self.settings.data["view_preferences"] = {
            "all_packages": self._last_scan_all_packages,
            "gallery": self._package_gallery_mode,
            "compact": self._package_gallery_compact,
            "sort_column": self._sort_state[0] if self._sort_state else "",
            "sort_reverse": self._sort_state[1] if self._sort_state else False,
            "icon_sort": self._icon_sort_active,
            "icon_grouped": self._icon_sort_grouped,
            "search": self.search_var.get()[:512],
        }

    def _toggle_preserve_settings(self) -> None:
        self.settings.data["preserve_settings"] = bool(self._preserve_settings_var.get())
        self._capture_view_preferences()
        try:
            self.settings.save()
        except OSError as exc:
            self._notify_user(f"Could not save display preferences: {exc}", level="warning")

    def _apply_startup_view(self) -> None:
        if not SHOWCASE_STARTUP:
            self._restore_view_preferences()
            return
        self._package_gallery_compact = False
        self._icon_sort_active, self._icon_sort_grouped = True, False
        self._sort_state = None
        self.search_var.set("")
        self._refresh_sort_headings("#0", " ▲")
        self._show_scan_view(True)
        self._set_package_gallery_mode(True)

    def _restore_view_preferences(self) -> None:
        if not self.settings.data.get("preserve_settings", False):
            return
        saved = self.settings.data.get("view_preferences", {})
        if not isinstance(saved, dict):
            return
        self._package_gallery_compact = saved.get("compact") is True
        column = saved.get("sort_column")
        self._sort_state = (column, saved.get("sort_reverse") is True) if isinstance(column, str) and column in self._tree_headings else None
        self._icon_sort_active = saved.get("icon_sort") is True
        self._icon_sort_grouped = saved.get("icon_grouped") is True
        search = saved.get("search", "")
        self.search_var.set(search[:512] if isinstance(search, str) else "")
        if saved.get("all_packages") is True:
            self._show_scan_view(True)
            self._set_package_gallery_mode(saved.get("gallery") is True)
        if self._icon_sort_active:
            self._refresh_sort_headings("#0", " △△" if self._icon_sort_grouped else " ▲")
        elif self._sort_state:
            column, reverse = self._sort_state
            self._refresh_sort_headings(column, " ▼" if reverse else " ▲")

    def _activate_all_packages(self) -> None:
        if self._last_scan_all_packages:
            self._set_package_gallery_mode(not self._package_gallery_mode)
        else:
            self._show_scan_view(True)

    def _set_package_gallery_mode(self, enabled: bool) -> None:
        self._stop_package_list_motion()
        self._stop_package_gallery_motion()
        self._package_gallery_mode = bool(enabled and self._last_scan_all_packages)
        self._cancel_after_id("_package_gallery_after_id")
        self._cancel_after_id("_package_gallery_icons_after_id")
        self._cancel_after_id("_details_idle_after_id")
        if not hasattr(self, "_package_gallery_frame"):
            return
        if self._package_gallery_mode:
            for widget in self._package_list_widgets:
                widget.grid_remove()
            self._package_gallery_frame.grid(row=0, column=0, rowspan=2, columnspan=2, sticky="nsew")
            self._package_gallery_canvas.focus_set()
            # The retained canvas owns its scroll position, just like the list.
            self._package_gallery_wheel_remainder = 0
            self._schedule_package_gallery_render(prime_resident=True)
            self._enqueue_gallery_idle_promotions()
        else:
            self._package_gallery_frame.grid_remove()
            for widget in self._package_list_widgets:
                widget.grid()
            self._package_gallery_canvas.delete("all")
            self._package_gallery_labels.clear()
            self._package_gallery_layouts.clear()
            self._package_gallery_focus_id = None
            self._package_gallery_images.clear()
            self._package_gallery_slots.clear()
            self._package_gallery_pending.clear()
            self._package_gallery_signature = None
            self._enqueue_gallery_idle_promotions()

    def _schedule_package_gallery_render(self, *, prime_resident: bool = False) -> None:
        if prime_resident:
            self._package_gallery_prime_resident = True
        if (not getattr(self, "_package_gallery_mode", False)
                or self._closing or self._package_gallery_after_id is not None):
            return
        self._package_gallery_after_id = self.root.after(0, self._render_package_gallery)

    def _package_gallery_icon_token(self, key: str) -> GalleryIconToken:
        return (self._icon_prepare_generation, max(48, self.visuals.px(DETAIL_ICON_SIZE_DIP)),
                self.palette["mode"], getattr(self, "_icon_item_revisions", {}).get(key, 0))

    def _package_gallery_icon_missing(self, item: UpdateItem) -> bool:
        """Read only current in-memory negative evidence; never probe the filesystem."""
        miss = self._package_gallery_misses.get(item.key)
        if miss is not None:
            if miss[0] == self._package_gallery_icon_token(item.key) and time.time() < miss[1]:
                return True
            self._package_gallery_misses.pop(item.key, None)
        entry = getattr(self, "_icon_catalog_entries", {}).get(item.key)
        if (not isinstance(entry, dict) or entry.get("identity") != list(item_icon_identity(item))
                or entry.get("version") != item.current):
            return False
        if icon_catalog_miss_is_current(entry, "details"):
            return True
        if not entry.get("source"):
            try:
                age = time.time() - float(entry.get("source_checked_at", 0))
            except (TypeError, ValueError):
                return False
            return 0 <= age <= ICON_CATALOG_NEGATIVE_SOURCE_TTL_SECONDS
        return False

    def _package_gallery_placeholder_allowed(self, item: UpdateItem) -> bool:
        if fallback_vector_style(item) != "wrench" or self._package_gallery_icon_missing(item):
            return True
        list_key = (item.key, max(12, self.visuals.px(PACKAGE_ICON_SIZE_DIP)), self.palette["mode"])
        return getattr(self, "_package_icon_images", {}).get(list_key) is not None

    def _package_gallery_memory_image(self, item: UpdateItem, token: GalleryIconToken) -> tuple[Any, bool]:
        """RAM-only peek: never stat, decode, generate artwork or start a worker."""
        preferred = preferred_vector_style(item)
        if preferred:
            image = self._provider_icon_images.get((preferred, token[1], token[2]))
            if image is not None:
                return image, True
        else:
            memory_key = (item.key, token[1], token[2])
            image = self._details_icon_images.get(memory_key)
            if image is not None:
                self._details_icon_images.move_to_end(memory_key)
                return image, True
        cached = self._package_gallery_images.get(item.key)
        if (cached is not None and cached[0] == token and cached[1] is not None
                and (cached[2] or self._package_gallery_placeholder_allowed(item))):
            return cached[1], cached[2]
        style = fallback_vector_style(item)
        image = (None if style == "wrench" and not self._package_gallery_icon_missing(item)
                 else self._provider_icon_images.get((style, token[1], token[2])))
        return image, False

    def _package_gallery_zoom(self, event: Any) -> str:
        if (not self._package_gallery_mode or self._closing or not event.delta
                or self._native_window_interaction_active()):
            return "break"
        now = time.monotonic()
        previous, self._package_gallery_zoom_time = self._package_gallery_zoom_time, now
        if now - previous < .20:
            return "break"  # One toggle per wheel gesture, including fine touchpad packets.
        self._stop_package_gallery_motion()
        _keys, columns, _cell, row = self._package_gallery_geometry
        self._package_gallery_zoom_anchor = max(0, int(self._package_gallery_canvas.canvasy(0) // row) * columns)
        self._package_gallery_compact = not self._package_gallery_compact
        self._package_gallery_signature = None
        self._schedule_package_gallery_render(prime_resident=True)
        return "break"

    def _compact_icon_if_resident(self, item: UpdateItem) -> Any | None:
        token = self._package_gallery_icon_token(item.key)
        key = (item.key, compact_gallery_size(token[1]), token[2])
        if self._compact_icon_tokens.get(key) == token:
            return self._compact_icon_images.get(key)
        self._compact_icon_images.pop(key, None)
        self._compact_icon_tokens.pop(key, None)
        return None

    def _package_gallery_display_image(self, image: Any, *, create: bool = False,
                                       item: UpdateItem | None = None) -> Any:
        if not self._package_gallery_compact:
            return image
        return self._package_gallery_compact_image(image, create=create, item=item)

    def _package_gallery_compact_image(self, image: Any, *, create: bool = False,
                                      item: UpdateItem | None = None) -> Any:
        """Pinned package lookup; creation is confined to budgeted acquisition."""
        size = compact_gallery_size(max(48, self.visuals.px(DETAIL_ICON_SIZE_DIP)))
        if item is not None and (cached := self._compact_icon_if_resident(item)) is not None:
            return cached
        if not create:
            cached = (getattr(image, "_windevpilot_compact_photo", None)
                      if getattr(image, "_windevpilot_compact_size", None) == size else None)
            if cached is not None and item is not None:
                token = self._package_gallery_icon_token(item.key)
                key = (item.key, size, token[2])
                self._compact_icon_images[key] = cached
                self._compact_icon_tokens[key] = token
            return cached
        scaled = None
        if item is not None and not preferred_vector_style(item):
            entry = getattr(self, "_icon_catalog_entries", {}).get(item.key, {})
            record = entry.get("compact", {})
            if (entry.get("identity") == list(item_icon_identity(item))
                    and entry.get("version") == item.current and record.get("size") == size):
                path = str(icon_cache_dir() / record["display"])
                if path in self._icon_catalog_blobs:
                    scaled = self._load_catalog_icon_image(path)
                if scaled is None:
                    return None  # Catalog artwork never enters the Python conversion path.
        if scaled is None and image is not None:
            scaled = getattr(image, "_windevpilot_compact_photo", None)
            if scaled is None or scaled.width() != size:
                png = getattr(image, "_windevpilot_source_png", None)
                decoded = read_png_rgba(png) if png is not None else None
                if decoded is None:
                    decoded = read_png_rgba(image.tk.call(str(image), "data", "-format", "png"))
                if decoded is None:
                    return None
                width, height, rows = decoded
                rows = _scale_rgba_nearest(rows, width, height, size, size)
                scaled = self.tk.PhotoImage(master=self.root, data=rgba_png_bytes(size, size, rows), format="png")
                image._windevpilot_compact_photo = scaled
                image._windevpilot_compact_size = size
        if scaled is not None and item is not None:
            token = self._package_gallery_icon_token(item.key)
            key = (item.key, size, token[2])
            self._compact_icon_images[key] = scaled
            self._compact_icon_tokens[key] = token
        return scaled

    def _publish_resident_gallery_icons(self) -> None:
        """Whole pending band: decoded lookups and widget assignments only."""
        cold = deque()
        for key in self._package_gallery_pending:
            item = self.items.get(key)
            if item is None or key not in self._package_gallery_slots:
                continue
            token = self._package_gallery_icon_token(key)
            if self._package_gallery_compact:
                photo = self._compact_icon_if_resident(item)
            else:
                photo, ready = self._package_gallery_memory_image(item, token)
                if not ready:
                    photo = None
                elif photo is not None:
                    self._package_gallery_images[key] = (token, photo, True)
            if photo is None:
                cold.append(key)
            else:
                self._package_gallery_canvas.itemconfigure(self._package_gallery_slots[key], image=photo)
        self._package_gallery_pending = cold
        self._report_gallery_warm_fill()

    def _report_gallery_warm_fill(self) -> None:
        """Report first normal viewport readiness once, including elapsed scheduling time."""
        if (self._package_gallery_compact or not hasattr(self, "logger")
                or getattr(self, "_gallery_warm_fill_reported", False)
                or not self._package_gallery_viewport_keys
                or self._package_gallery_viewport_keys.intersection(self._package_gallery_pending)):
            return
        if any(not (self._package_gallery_images.get(key, (None, None, False))[2]
                    or self._package_gallery_icon_missing(self.items[key]))
               for key in self._package_gallery_viewport_keys if key in self.items):
            return  # A queued extraction can temporarily leave the publication queue empty.
        started = getattr(self, "_gallery_warm_fill_started", None)
        if started is not None:
            self._gallery_warm_fill_reported = True
            self.logger.event("icon_warm_fill", tier="details-viewport",
                              count=len(self._package_gallery_viewport_keys),
                              seconds=round(time.perf_counter() - started, 4))

    def _render_package_gallery(self) -> None:
        self._cancel_after_id("_package_gallery_after_id")
        if not self._package_gallery_mode or self._closing:
            return
        if self._native_window_interaction_active():
            self._package_gallery_after_id = self.root.after(
                WINDOW_DRAG_BUSY_ANIMATION_POLL_MS, self._render_package_gallery)
            return
        deadline = time.perf_counter() + PACKAGE_GALLERY_FIRST_PAINT_BUDGET_SECONDS
        if not self._package_gallery_compact and not hasattr(self, "_gallery_warm_fill_started"):
            self._gallery_warm_fill_started = deadline - PACKAGE_GALLERY_FIRST_PAINT_BUDGET_SECONDS
        prime_resident = self._package_gallery_prime_resident
        self._package_gallery_prime_resident = False
        canvas = self._package_gallery_canvas
        px = self.visuals.px
        keys = getattr(self, "_tree_display_order", None)
        if keys is None:
            keys = tuple(self.tree.get_children())
        width, height = max(1, canvas.winfo_width()), max(1, canvas.winfo_height())
        resource_size = max(48, px(DETAIL_ICON_SIZE_DIP))
        scale = PACKAGE_GALLERY_COMPACT_SCALE if self._package_gallery_compact else 1.0
        size = round(resource_size * scale)
        columns = max(1, width // max(1, round(px(132) * scale)))
        cell_width, row_height = width / columns, size + px(45)
        self._package_gallery_geometry = (keys, columns, cell_width, row_height)
        extent = (width, max(height, ((len(keys) + columns - 1) // columns) * row_height))
        if (extent != getattr(self, "_package_gallery_extent", None)
                or (width, height) != getattr(self, "_package_gallery_viewport_size", None)):
            self._stop_package_gallery_motion()
            self._package_gallery_viewport_size = (width, height)
        if extent != getattr(self, "_package_gallery_extent", None):
            self._package_gallery_extent = extent
            canvas.configure(scrollregion=(0, 0, *extent), yscrollincrement=1)
        if self._package_gallery_zoom_anchor is not None:
            top = (self._package_gallery_zoom_anchor // columns) * row_height
            self._package_gallery_zoom_anchor = None
            canvas.yview_moveto(min(top, max(0, extent[1] - height)) / max(1, extent[1]))
        top = canvas.canvasy(0)
        first = max(0, int(top // row_height) - 1) * columns
        stop = min(len(keys), (int((top + height) // row_height) + 2) * columns)
        visible = keys[first:stop]
        font = self._ui_font(10)
        focus = self.tree.focus()
        base_token = (self._icon_prepare_generation, resource_size, self.palette["mode"])
        revisions = getattr(self, "_icon_item_revisions", {})
        tokens = {key: (*base_token, revisions.get(key, 0)) for key in visible}
        # The viewport can cross a row while the retained overscan band stays the
        # same near an end. Refresh eligibility even when tile rendering is skipped.
        viewport_first = max(first, int(top // row_height) * columns)
        viewport_stop = min(stop, (int((top + height) // row_height) + 1) * columns)
        viewport = self._package_gallery_viewport_keys = set(keys[viewport_first:viewport_stop])
        signature = (width, height, columns, size, first, visible, font, self.palette["text"],
                     self.palette["accent_2"], tuple(
                         (self.items[key].name, tokens[key]) for key in visible), focus)
        if signature == getattr(self, "_package_gallery_signature", None):
            return
        self._package_gallery_signature = signature
        # Keep the pump's deadline while replacing its work queue. Frequent layout
        # changes must not keep postponing a timer that is already due to run.
        wanted = set(visible)
        retain = set(keys[max(0, first - (stop - first)):min(len(keys), stop + (stop - first))])
        self._package_gallery_images = {
            key: cached for key, cached in self._package_gallery_images.items()
            if key in retain and cached[0] == self._package_gallery_icon_token(key)
        }
        if self._package_gallery_scaled_context != base_token:
            self._compact_icon_images.clear()
            self._compact_icon_tokens.clear()
            self._package_gallery_scaled_context = base_token
        slots, labels, layouts = self._package_gallery_slots, self._package_gallery_labels, self._package_gallery_layouts
        reusable = []
        for key in tuple(slots):
            if key not in wanted:
                reusable.append((slots.pop(key), labels.pop(key)))
                layouts.pop(key, None)
        pending = []
        for index in range(first, stop):
            key = keys[index]
            item = self.items[key]
            x = (index % columns + 0.5) * cell_width
            y = (index // columns) * row_height + px(6)
            new_slot = key not in slots
            if new_slot:
                if reusable:
                    slots[key], labels[key] = reusable.pop()
                else:
                    slots[key] = canvas.create_image(0, 0)
                    labels[key] = canvas.create_text(0, 0, anchor="n", justify="center")
            layout = (x, y, size, cell_width, row_height, item.name, font, self.palette["text"])
            layout_changed = layouts.get(key) != layout
            if layout_changed:
                layouts[key] = layout
                canvas.coords(slots[key], x + self._package_gallery_side_offset, y + size / 2)
                canvas.coords(labels[key], x + self._package_gallery_side_offset, y + size + px(4))
                name = item.name[:160] + ("…" if len(item.name) > 160 else "")
                text_width, text_height = max(1, cell_width - px(12)), px(30)
                fit_key = (name, font, text_width, text_height, getattr(self.visuals, "current_dpi", 96))
                fitted = self._package_gallery_fitted_names.get(fit_key)
                canvas.itemconfigure(labels[key], text=name if fitted is None else fitted, width=text_width,
                                     font=font, fill=self.palette["text"])
                if fitted is None:
                    # Keep the existing measured output, including its ellipsis rules.
                    while len(name) > 1:
                        bounds = canvas.bbox(labels[key])
                        if bounds is None or bounds[3] - bounds[1] <= text_height:
                            break
                        name = name[:-1].rstrip()
                        canvas.itemconfigure(labels[key], text=name + "…")
                    self._package_gallery_fitted_names[fit_key] = canvas.itemcget(labels[key], "text")
                    if len(self._package_gallery_fitted_names) > 2048:
                        self._package_gallery_fitted_names.popitem(last=False)
                self._package_gallery_fitted_names.move_to_end(fit_key)
            token = tokens[key]
            image, ready = self._package_gallery_memory_image(item, token)
            displayed = self._package_gallery_display_image(image, item=item)
            if self._package_gallery_compact and displayed is not None:
                ready = True
            previous = self._package_gallery_images.get(key)
            if new_slot or layout_changed or previous is None or previous[1] is not image:
                canvas.itemconfigure(slots[key], image=displayed if displayed is not None else "")
            if image is not None:
                self._package_gallery_images[key] = (token, image, ready)
            if not ready or (image is not None and displayed is None):
                pending.append(key)
        for image_id, label_id in reusable:
            canvas.delete(image_id, label_id)
        # One outline moves independently of the retained image/text pairs.
        if focus in wanted:
            index = first + visible.index(focus)
            x, y = (index % columns + 0.5) * cell_width, (index // columns) * row_height + px(6)
            x += self._package_gallery_side_offset
            if self._package_gallery_focus_id is None:
                self._package_gallery_focus_id = canvas.create_rectangle(0, 0, 0, 0)
            canvas.coords(self._package_gallery_focus_id, x - cell_width / 2 + px(4), y - px(3),
                          x + cell_width / 2 - px(4), y + row_height - px(9))
            canvas.itemconfigure(self._package_gallery_focus_id, outline=self.palette["accent_2"], state="normal")
            canvas.tag_lower(self._package_gallery_focus_id)
        elif self._package_gallery_focus_id is not None:
            canvas.itemconfigure(self._package_gallery_focus_id, state="hidden")
        # Actual viewport first, then the small overscan band.
        pending.sort(key=lambda key: key not in viewport)
        self._package_gallery_pending = deque(pending)
        self._report_gallery_warm_fill()
        if pending:
            if prime_resident and time.perf_counter() < deadline:
                self._cancel_after_id("_package_gallery_icons_after_id")
                self._pump_package_gallery_icons(resident_deadline=deadline)
            elif self._package_gallery_icons_after_id is None:
                self._package_gallery_icons_after_id = self.root.after(1, self._pump_package_gallery_icons)

    def _pump_package_gallery_icons(self, *, resident_deadline: float | None = None) -> None:
        self._package_gallery_icons_after_id = None
        if not self._package_gallery_mode or self._closing or not self._package_gallery_pending:
            return
        if getattr(self, "_cache_clear_inflight", False) or self._native_window_interaction_active():
            self._package_gallery_icons_after_id = self.root.after(100, self._pump_package_gallery_icons)
            return
        self._publish_resident_gallery_icons()
        if not self._package_gallery_pending:
            return
        drag = getattr(self, "_package_gallery_drag", None)
        first_paint = resident_deadline is not None
        if first_paint and (drag is not None or getattr(self, "_package_gallery_motion_after_id", None) is not None):
            self._package_gallery_icons_after_id = self.root.after(16, self._pump_package_gallery_icons)
            return
        moving = ((drag is not None and drag["active"])
                  or getattr(self, "_package_gallery_motion_after_id", None) is not None
                  or time.monotonic() < getattr(self, "_details_idle_quiet_until", 0.0))
        if moving and hasattr(self, "logger"):
            now = time.monotonic()
            if now - getattr(self, "_gallery_miss_logged_at", 0.0) >= 1.0:
                self._gallery_miss_logged_at = now
                self.logger.event("gallery_scroll_miss", count=len(self._package_gallery_pending),
                                  compact=self._package_gallery_compact)
        # Motion keeps Tk on a soft 1-ms slice of resident photos/prepared bytes,
        # including vectors: visible work must not require an idle interval.
        # One visible cold request per tick uses the existing two-job cap.
        deadline = (resident_deadline if first_paint else
                    time.perf_counter() + (.001 if moving else PACKAGE_GALLERY_ICON_TIME_BUDGET_SECONDS))
        # Each key is examined at most once per slice, including deferred cold jobs.
        remaining = len(self._package_gallery_pending)
        motion_prepare_started = False
        while remaining and self._package_gallery_pending:
            remaining -= 1
            key = self._package_gallery_pending.popleft()
            if first_paint and key not in self._package_gallery_viewport_keys:
                self._package_gallery_pending.append(key)
                if time.perf_counter() >= deadline:
                    break
                continue
            item = self.items.get(key)
            if item is not None and key in self._package_gallery_slots:
                token = self._package_gallery_icon_token(key)
                if self._package_gallery_compact:
                    compact = self._package_gallery_compact_image(None, item=item, create=True)
                    if compact is not None:
                        self._package_gallery_canvas.itemconfigure(self._package_gallery_slots[key], image=compact)
                        if time.perf_counter() >= deadline:
                            break
                        continue
                image = (self._details_icon_image_if_ready(item, token[1], resident_only=True)
                         if moving or first_paint else self._details_icon_image_if_ready(item, token[1]))
                ready = image is not None
                if not first_paint and image is None:
                    image = self._resident_vector_icon_image(item, token[1])
                    ready = image is not None and bool(preferred_vector_style(item))
                cached = self._package_gallery_images.get(key)
                if (moving or first_paint) and image is None:
                    self._package_gallery_pending.append(key)
                    if (not first_paint and not motion_prepare_started and key in self._package_gallery_viewport_keys
                            and self._package_gallery_attempts.get(key) != token
                            and not preferred_vector_style(item)
                            and not self._package_gallery_icon_missing(item)
                            and sum(job[0].startswith("details:package-gallery:")
                                    for job in self._icon_prepare_inflight) < 2):
                        self._package_gallery_attempts[key] = token
                        self._queue_details_icon_prepare(
                            item, token[1], lambda finished, expected=token: self._package_gallery_icon_ready(finished, expected),
                            coalesce_key=f"package-gallery:{key}")
                        motion_prepare_started = True
                    if time.perf_counter() >= deadline:
                        break
                    continue
                if not ready and image is None:
                    if self._package_gallery_placeholder_allowed(item):
                        image = (cached[1] if cached and cached[0] == token and cached[1] is not None
                                 else self._details_icon_placeholder(item, token[1])[0])
                    else:
                        image = None  # Keep the icon space quiet while its artwork is unresolved.
                self._package_gallery_images[key] = (token, image, ready)
                displayed = self._package_gallery_display_image(image, create=True, item=item)
                if ready and displayed is None:
                    # A catalog record may arrive before its worker-delivered bytes.
                    # Keep the tile pending and let the same bounded worker fill it.
                    ready = False
                if cached is None or cached[0] != token or cached[1] is not image or self._package_gallery_compact:
                    self._package_gallery_canvas.itemconfigure(self._package_gallery_slots[key], image=displayed if displayed is not None else "")
                attempted = self._package_gallery_attempts.get(key) == token
                active = sum(job[0].startswith("details:package-gallery:") for job in self._icon_prepare_inflight)
                if not ready and not attempted and not self._package_gallery_icon_missing(item):
                    if active < 2:
                        self._package_gallery_attempts[key] = token
                        self._queue_details_icon_prepare(
                            item, token[1], lambda finished, expected=token: self._package_gallery_icon_ready(finished, expected),
                            coalesce_key=f"package-gallery:{key}",
                        )
                    else:
                        self._package_gallery_pending.append(key)
                elif not ready and image is not None and displayed is None:
                    self._package_gallery_pending.append(key)
            if time.perf_counter() >= deadline:
                break
        if self._package_gallery_pending:
            # A positive continuation yields to input/repaint. Only capacity waits use 24 ms.
            self._package_gallery_icons_after_id = self.root.after(
                1 if first_paint else (16 if moving else (1 if remaining else 24)), self._pump_package_gallery_icons)
        self._report_gallery_warm_fill()

    def _package_gallery_icon_ready(self, key: str, token: GalleryIconToken) -> None:
        if (not self._package_gallery_mode or self._closing or key not in self._package_gallery_slots
                or key not in self.items or token != self._package_gallery_icon_token(key)):
            return
        # One publication path owns decoding, batching and interaction guards.
        if key not in self._package_gallery_pending:
            self._package_gallery_pending.append(key)
        if self._package_gallery_icons_after_id is None:
            self._package_gallery_icons_after_id = self.root.after(1, self._pump_package_gallery_icons)

    def _stop_package_gallery_motion(self, *, settle: bool = True) -> None:
        self._cancel_after_id("_package_gallery_motion_after_id")
        self._cancel_after_id("_package_gallery_drag_after_id")
        self._package_gallery_drag = None
        self._package_gallery_velocity = 0.0
        self._package_gallery_wheel_target = None
        self._package_gallery_bounce_state = None
        self._package_gallery_side_return = None
        if canvas := getattr(self, "_package_gallery_canvas", None):
            with contextlib.suppress(self.tk.TclError):
                canvas.configure(cursor="")
                if settle:
                    self._set_package_gallery_side_offset(0)
                if settle and self._package_gallery_elastic:
                    self._package_gallery_elastic = False
                    extent = self._package_gallery_extent[1]
                    self._package_gallery_scroll_position = max(0.0, min(
                        max(0, extent - canvas.winfo_height()), self._package_gallery_scroll_position))
                    canvas.configure(confine=True)
                    canvas.yview_moveto(self._package_gallery_scroll_position / max(1, extent))

    def _package_gallery_scroll_to(self, top: float, *, elastic: bool = False) -> bool:
        """Move in pixels, retaining a fractional target for time-based momentum."""
        canvas = self._package_gallery_canvas
        extent = self._package_gallery_extent[1]
        maximum = max(0, extent - canvas.winfo_height())
        allowance = min(self.visuals.px(72), canvas.winfo_height() * .2) if elastic else 0
        target = max(-allowance, min(float(maximum) + allowance, top))
        stretched = target < 0 or target > maximum
        if stretched != self._package_gallery_elastic:
            self._package_gallery_elastic = stretched
            canvas.configure(confine=not stretched)
        self._package_gallery_scroll_position = target
        # Keep exact physics even when several ticks land on the same displayed
        # pixel. Tk rounds positive scroll positions to the nearest pixel.
        pixel = math.floor(target + .5)
        current_pixel = canvas.canvasy(0)
        if pixel != current_pixel:
            # Integer unit deltas also handle negative elastic coordinates
            # without yview_moveto's asymmetric rounding around zero.
            canvas.yview_scroll(int(pixel - current_pixel), "units")
            self._render_package_gallery()
        return 0 < target < maximum

    def _package_gallery_elastic_target(self, top: float) -> float:
        """Increasing resistance limits exposed blank space to 72 DIPs/20% height."""
        height = self._package_gallery_viewport_size[1]
        maximum = max(0, self._package_gallery_extent[1] - height)
        boundary = max(0.0, min(float(maximum), top))
        distance = top - boundary
        return boundary + self._package_gallery_resisted_distance(distance)

    def _package_gallery_resisted_distance(self, distance: float) -> float:
        # Both axes expose the same amount of whitespace for the same pull.
        limit = max(1, min(self.visuals.px(72), self._package_gallery_viewport_size[1] * .2))
        return limit * distance / (2 * limit + abs(distance))

    def _set_package_gallery_side_offset(self, offset: float) -> None:
        """Translate retained artwork in one Tk call; never change horizontal view."""
        pixel = math.floor(offset + .5)
        previous = self._package_gallery_side_offset
        if pixel != previous:
            self._package_gallery_canvas.move("all", pixel - previous, 0)
            self._package_gallery_side_offset = pixel

    def _advance_package_gallery_side_return(self) -> None:
        state = self._package_gallery_side_return
        if state is None:
            return
        displacement, started = state
        elapsed = max(0.0, time.monotonic() - started)
        offset = displacement * (1 + 18 * elapsed) * math.exp(-18 * elapsed)
        if abs(offset) < .35 or elapsed >= .7:
            offset = 0.0
            self._package_gallery_side_return = None
        self._set_package_gallery_side_offset(offset)

    def _finish_package_gallery_vertical_motion(self) -> None:
        """Let the side spring finish on the same timer after vertical motion ends."""
        self._package_gallery_velocity = 0.0
        self._package_gallery_wheel_target = None
        self._package_gallery_bounce_state = None
        if self._package_gallery_side_return is not None:
            self._schedule_package_gallery_motion(self._package_gallery_side_bounce)
        else:
            self._stop_package_gallery_motion()

    def _package_gallery_side_bounce(self) -> None:
        self._package_gallery_motion_after_id = None
        if not self._package_gallery_mode or self._closing or self._native_window_interaction_active():
            self._stop_package_gallery_motion()
            return
        self._advance_package_gallery_side_return()
        self._finish_package_gallery_vertical_motion()

    def _package_gallery_press(self, event: Any) -> str:
        self._stop_package_gallery_motion(settle=False)
        if not self._package_gallery_mode or self._closing:
            return "break"
        canvas = self._package_gallery_canvas
        canvas.focus_set()
        self._package_gallery_click(event)
        top = canvas.canvasy(0)
        maximum = max(0, self._package_gallery_extent[1] - self._package_gallery_viewport_size[1])
        boundary = max(0.0, min(float(maximum), top))
        offset = top - boundary
        limit = max(1, min(self.visuals.px(72), self._package_gallery_viewport_size[1] * .2))
        # Invert the resistance curve when catching an existing bounce, keeping
        # its current visual position rather than snapping before the next drag.
        raw_top = boundary + 2 * limit * offset / max(1, limit - abs(offset))
        side = self._package_gallery_side_offset
        self._package_gallery_drag = {
            "x": event.x, "y": event.y, "last_x": event.x, "last_y": event.y,
            "active": False, "side_active": bool(side),
            "side": 2 * limit * side / max(1, limit - abs(side)),
            "top": raw_top, "samples": deque([(time.monotonic(), top)], maxlen=32),
        }
        return "break"

    def _package_gallery_drag_move(self, event: Any) -> str:
        drag = self._package_gallery_drag
        if drag is None or not self._package_gallery_mode or self._closing:
            return "break"
        delta = drag["last_y"] - event.y
        sideways = event.x - drag["last_x"]
        drag["last_x"], drag["last_y"] = event.x, event.y
        if not drag["active"]:
            if max(abs(event.x - drag["x"]), abs(event.y - drag["y"])) < self.visuals.px(6):
                return "break"
            drag["active"] = True
            self._package_gallery_canvas.configure(cursor="hand2")
            delta = drag["y"] - event.y
            sideways = event.x - drag["x"]
        if not drag["side_active"]:
            distance = event.x - drag["x"]
            threshold = self.visuals.px(48)
            if abs(distance) > threshold:
                drag["side_active"] = True
                # Consume the dead zone: crossing it starts at zero stretch,
                # rather than jumping by the full accumulated horizontal drift.
                sideways = distance - math.copysign(threshold, distance)
            else:
                sideways = 0
        drag["side"] += sideways
        drag["top"] += delta
        now = time.monotonic()
        samples = drag["samples"]
        position = self._package_gallery_elastic_target(drag["top"])
        # Keep the latest position in each 8-ms bucket: bounded storage with a
        # consistent history even when many mouse packets arrive between paints.
        if len(samples) > 1 and int(now / .008) == int(samples[-1][0] / .008):
            samples[-1] = (now, position)
        else:
            samples.append((now, position))
        while len(samples) > 2 and samples[0][0] < now - .12:
            samples.popleft()
        if self._package_gallery_drag_after_id is None:
            self._package_gallery_drag_after_id = self.root.after(8, self._flush_package_gallery_drag)
        return "break"

    def _flush_package_gallery_drag(self) -> None:
        self._cancel_after_id("_package_gallery_drag_after_id")
        drag = self._package_gallery_drag
        if drag is not None and drag["active"] and self._package_gallery_mode and not self._closing:
            self._set_package_gallery_side_offset(self._package_gallery_resisted_distance(drag["side"]))
            target = self._package_gallery_elastic_target(drag["top"])
            if target != drag["top"]:
                self._package_gallery_scroll_to(target, elastic=True)
            else:
                self._package_gallery_scroll_to(target)

    def _package_gallery_release(self, event: Any) -> str:
        drag = self._package_gallery_drag
        if drag is None:
            return "break"
        if (event.x, event.y) != (drag["last_x"], drag["last_y"]):
            self._package_gallery_drag_move(event)
        if drag["active"]:
            self._flush_package_gallery_drag()
        # Layout/view changes during the gesture cancel it instead of targeting a new tile.
        if self._package_gallery_drag is not drag:
            return "break"
        self._package_gallery_drag = None
        self._package_gallery_canvas.configure(cursor="")
        if self._package_gallery_side_offset:
            now = time.monotonic()
            self._package_gallery_side_return = (self._package_gallery_side_offset, now)
            self._package_gallery_motion_deadline = now
        if self._package_gallery_elastic:
            self._start_package_gallery_bounce()
            return "break"
        if not drag["active"]:
            self._finish_package_gallery_vertical_motion()
            return "break"
        now = time.monotonic()
        samples = drag["samples"]
        if now - samples[-1][0] > .10:
            self._finish_package_gallery_vertical_motion()
            return "break"  # A deliberate pause before release should stop the content.
        samples.append((now, self._package_gallery_scroll_position))
        while len(samples) > 2 and samples[0][0] < now - .12:
            samples.popleft()
        elapsed = now - samples[0][0]
        velocity = (samples[-1][1] - samples[0][1]) / elapsed if elapsed >= .01 else 0.0
        limit = self.visuals.px(3600)
        self._package_gallery_velocity = max(-limit, min(limit, velocity))
        if abs(self._package_gallery_velocity) >= self.visuals.px(80):
            self._package_gallery_motion_time = now
            self._package_gallery_motion_deadline = now + .016
            self._package_gallery_motion_after_id = self.root.after(16, self._package_gallery_coast)
        else:
            self._finish_package_gallery_vertical_motion()
        return "break"

    def _package_gallery_coast(self) -> None:
        self._package_gallery_motion_after_id = None
        if not self._package_gallery_mode or self._closing or self._native_window_interaction_active():
            self._stop_package_gallery_motion()
            return
        now = time.monotonic()
        elapsed = max(0.0, now - self._package_gallery_motion_time)
        self._package_gallery_motion_time = now
        if elapsed > .12:
            self._stop_package_gallery_motion()
            return  # Do not jump after a delayed event loop or suspended window.
        decay = math.exp(-elapsed / .30)
        self._advance_package_gallery_side_return()
        velocity = self._package_gallery_velocity
        target = self._package_gallery_scroll_position + velocity * .30 * (1 - decay)
        resisted = self._package_gallery_elastic_target(target)
        if resisted != target:
            self._package_gallery_scroll_to(resisted, elastic=True)
            self._start_package_gallery_bounce(velocity * .35)
            return
        moving = self._package_gallery_scroll_to(target)
        self._package_gallery_velocity *= decay
        if moving and abs(self._package_gallery_velocity) >= self.visuals.px(12):
            self._schedule_package_gallery_motion(self._package_gallery_coast)
        else:
            self._finish_package_gallery_vertical_motion()

    def _schedule_package_gallery_motion(self, callback: Callable[[], None]) -> None:
        # Pace from deadlines; skip elapsed slots instead of catch-up callbacks.
        finished = time.monotonic()
        deadline = getattr(self, "_package_gallery_motion_deadline", finished) + .016
        if deadline <= finished:
            deadline += (math.floor((finished - deadline) / .016) + 1) * .016
        self._package_gallery_motion_deadline = deadline
        delay = max(1, math.ceil((deadline - finished) * 1000))
        self._package_gallery_motion_after_id = self.root.after(delay, callback)

    def _start_package_gallery_bounce(self, velocity: float = 0.0) -> None:
        if not self._package_gallery_elastic:
            return
        position = self._package_gallery_scroll_position
        maximum = max(0, self._package_gallery_extent[1] - self._package_gallery_viewport_size[1])
        boundary = max(0.0, min(float(maximum), position))
        self._package_gallery_bounce_state = (
            boundary, position - boundary,
            max(-self.visuals.px(1000), min(self.visuals.px(1000), velocity)), time.monotonic())
        self._package_gallery_motion_deadline = self._package_gallery_bounce_state[3] + .016
        self._package_gallery_motion_after_id = self.root.after(16, self._package_gallery_bounce)

    def _package_gallery_bounce(self) -> None:
        self._package_gallery_motion_after_id = None
        state = self._package_gallery_bounce_state
        if (state is None or not self._package_gallery_mode or self._closing
                or self._native_window_interaction_active()):
            self._stop_package_gallery_motion()
            return
        boundary, displacement, velocity, started = state
        self._advance_package_gallery_side_return()
        elapsed = max(0.0, time.monotonic() - started)
        # Closed-form damped spring: bounded return with no accumulated timer error.
        offset = (displacement + (velocity + 18 * displacement) * elapsed) * math.exp(-18 * elapsed)
        if abs(offset) < .35 or elapsed >= .7:
            self._package_gallery_scroll_to(boundary)
            self._finish_package_gallery_vertical_motion()
            return
        self._package_gallery_scroll_to(boundary + offset, elastic=True)
        if self._package_gallery_bounce_state is state:
            self._schedule_package_gallery_motion(self._package_gallery_bounce)

    def _package_gallery_wheel(self, event: Any) -> str:
        if not self._package_gallery_mode or self._closing or self._native_window_interaction_active():
            self._stop_package_gallery_motion()
            return "break"
        total = getattr(self, "_package_gallery_wheel_remainder", 0) - event.delta * 3
        steps = int(total / 120)
        self._package_gallery_wheel_remainder = total - steps * 120
        if not steps:
            if not event.delta:
                self._stop_package_gallery_motion()
            return "break"
        previous = self._package_gallery_wheel_target
        if previous is None:
            side_return = self._package_gallery_side_return
            self._stop_package_gallery_motion(settle=False)
            if self._package_gallery_side_offset:
                self._package_gallery_side_return = side_return or (self._package_gallery_side_offset, time.monotonic())
            self._package_gallery_scroll_position = self._package_gallery_canvas.canvasy(0)
        maximum = max(0, self._package_gallery_extent[1] - self._package_gallery_viewport_size[1])
        base = previous[0] if previous is not None else max(
            0.0, min(float(maximum), self._package_gallery_scroll_position))
        requested = base + steps * max(1, self.visuals.px(24))
        destination = max(0.0, min(float(maximum), requested))
        self._package_gallery_wheel_target = (destination, self._package_gallery_elastic_target(requested))
        self._note_icon_idle_activity()
        if previous is None:
            now = time.monotonic()
            self._package_gallery_motion_time = now
            self._package_gallery_motion_deadline = now + .016
            self._package_gallery_motion_after_id = self.root.after(16, self._package_gallery_wheel_tick)
        return "break"

    def _package_gallery_wheel_tick(self) -> None:
        self._package_gallery_motion_after_id = None
        target = self._package_gallery_wheel_target
        if (target is None or not self._package_gallery_mode or self._closing
                or self._native_window_interaction_active()):
            self._stop_package_gallery_motion()
            return
        now = time.monotonic()
        elapsed = max(0.0, now - self._package_gallery_motion_time)
        self._package_gallery_motion_time = now
        if elapsed > .12:
            self._stop_package_gallery_motion()
            return  # Match drag momentum's no-jump policy after a delayed event loop.
        destination, aim = target
        self._advance_package_gallery_side_return()
        position = self._package_gallery_scroll_position
        remaining = aim - position
        decay = math.exp(-elapsed / PACKAGE_GALLERY_WHEEL_DECAY_SECONDS)
        position += remaining * (1 - decay)
        self._package_gallery_scroll_to(position, elastic=True)
        if self._package_gallery_wheel_target is not target:
            return  # A resize or view change during rendering canceled this motion.
        if self._package_gallery_elastic and aim != destination:
            self._package_gallery_wheel_target = None
            self._start_package_gallery_bounce(remaining / PACKAGE_GALLERY_WHEEL_DECAY_SECONDS * .35)
        elif abs(aim - position) < .35:
            self._package_gallery_scroll_to(destination)
            self._finish_package_gallery_vertical_motion()
        else:
            self._schedule_package_gallery_motion(self._package_gallery_wheel_tick)

    def _package_gallery_key_at(self, event: Any) -> str:
        if not self._package_gallery_mode:
            return ""
        canvas = self._package_gallery_canvas
        if not (0 <= event.x < canvas.winfo_width() and 0 <= event.y < canvas.winfo_height()):
            return ""
        keys, columns, cell_width, row_height = self._package_gallery_geometry
        x = event.x - self._package_gallery_side_offset
        if not 0 <= x < columns * cell_width:
            return ""
        index = int(canvas.canvasy(event.y) // row_height) * columns + int(x // cell_width)
        return keys[index] if 0 <= index < len(keys) and keys[index] in self.items else ""

    def _package_gallery_click(self, event: Any, key: str | None = None) -> str:
        if key is None:
            key = self._package_gallery_key_at(event)
        if key:
            self.tree.selection_set(key)
            self.tree.focus(key)
            self._schedule_package_gallery_render()
        return "break"

    def _package_gallery_double_click(self, event: Any) -> str:
        # Use the same Tk double-click event as the list. Its
        # double-click binding replaces the second press's single-click binding.
        key = self._package_gallery_key_at(event)
        self._stop_package_gallery_motion()
        if not self._closing and key:
            self._package_gallery_canvas.focus_set()
            self._package_gallery_click(event, key)
            self.show_item_details(self.items[key], reuse_quick_window=True)
        return "break"

    def _package_gallery_context_menu(self, event: Any) -> str:
        key = self._package_gallery_key_at(event)
        self._stop_package_gallery_motion()
        if key:
            self._schedule_package_gallery_render()
            return self._show_package_context_menu(key, event, self._package_gallery_canvas)
        return "break"

    def _package_gallery_key(self, event: Any) -> str:
        self._stop_package_gallery_motion()
        if event.keysym == "Escape":
            return "break"
        keys, columns, _cell_width, row_height = self._package_gallery_geometry
        if not keys:
            return "break"
        current = self.tree.focus()
        index = keys.index(current) if current in keys else 0
        if event.keysym == "Return":
            self.show_item_details(self.items[keys[index]], reuse_quick_window=True)
            return "break"
        page = max(1, self._package_gallery_canvas.winfo_height() // row_height) * columns
        offset = {"Left": -1, "Right": 1, "Up": -columns, "Down": columns,
                  "Prior": -page, "Next": page, "Home": -len(keys), "End": len(keys)}[event.keysym]
        index = max(0, min(len(keys) - 1, index + offset))
        self.tree.focus(keys[index])
        canvas = self._package_gallery_canvas
        top = (index // columns) * row_height
        view_top, height = canvas.canvasy(0), canvas.winfo_height()
        if top < view_top or top + row_height > view_top + height:
            target = top if top < view_top else top + row_height - height
            canvas.yview_moveto(max(0, target) / self._package_gallery_extent[1])
        self._schedule_package_gallery_render()
        return "break"

    def _show_scan_view(
        self, all_packages: bool, *, force: bool = False,
        retained_icon_keys: set[str] | None = None,
    ) -> None:
        if not force and all_packages == self._last_scan_all_packages:
            return
        if not all_packages or not self._last_scan_all_packages:
            self._set_package_gallery_mode(False)
        self._scan_view_items[self._last_scan_all_packages] = self.items
        self._last_scan_all_packages = all_packages
        self.items = self._scan_view_items[all_packages]
        self._set_header_title("Installed Applications" if all_packages else "Updates")
        self._refresh_scan_view_buttons()
        self._icon_prepare_generation += 1
        getattr(self, "_package_gallery_misses", {}).clear()
        self._package_gallery_attempts.clear()
        self.icon_renderer.set_generation(self._icon_prepare_generation, terminate=False)
        self._icon_resolution_generation += 1
        self._icon_prepare_inflight.clear()
        self._details_icon_callbacks.clear()
        if force:
            evidence = getattr(self, "_details_icon_evidence_cache", {})
            if retained_icon_keys is None:
                self._details_icon_images.clear()
                getattr(self, "_compact_icon_images", {}).clear()
                getattr(self, "_compact_icon_tokens", {}).clear()
                evidence.clear()
            else:
                # Scan completion already checked identity, version and source
                # evidence. Renew worker ownership without discarding valid pixels.
                for cache in (self._details_icon_images, self._compact_icon_images, self._compact_icon_tokens, evidence):
                    for key in list(cache):
                        if key[0] not in retained_icon_keys:
                            del cache[key]
                self._package_gallery_images = {
                    key: (self._package_gallery_icon_token(key), image, ready)
                    for key, (token, image, ready) in self._package_gallery_images.items()
                    if key in retained_icon_keys
                    and token[1:] == self._package_gallery_icon_token(key)[1:]
                }
                if self._package_gallery_scaled_context is not None:
                    self._package_gallery_scaled_context = (
                        self._icon_prepare_generation, *self._package_gallery_scaled_context[1:])
        self._compact_icon_tokens = {key: self._package_gallery_icon_token(key[0])
                                     for key in self._compact_icon_images}
        self._package_gallery_scaled_context = (self._icon_prepare_generation,
            max(48, self.visuals.px(DETAIL_ICON_SIZE_DIP)), self.palette["mode"])
        self._reset_ready_icon_memory_load()
        self._reset_background_icon_sweep()
        self._reset_background_details_icon_sweep()
        self._lazy_icon_log_announced = False
        self._cancel_after_id("_rebuild_after_id")
        self._rebuild_prime_cached_first_paint = False
        if self._native_window_interaction_active():
            # Publish completion and status immediately; only the expensive
            # table repaint waits for the exclusive native move/size gesture.
            self._schedule_rebuild_tree(prime_cached_first_paint=True)
        else:
            self._rebuild_tree(prime_cached_first_paint=True)
        icon_size = max(12, self.visuals.px(PACKAGE_ICON_SIZE_DIP))
        palette_mode = self.palette["mode"]
        retained_icon_index_complete = bool(self.items) and all(
            key in self._item_icon_source_cache
            and (
                (key, icon_size, palette_mode) in self._package_icon_images
                or (key, icon_size, palette_mode) in self._package_icon_ready
                or (key, icon_size, palette_mode) in self._package_icon_misses
            )
            for key in self.items
        )
        ready_for_view = [
            (key, icon_size, palette_mode)
            for key in self.items
            if (key, icon_size, palette_mode) in self._package_icon_ready
        ]
        if ready_for_view:
            # View changes intentionally cancel stale decode work; immediately
            # refill the queue from the retained warm index instead of waiting
            # for scrolling to request each cached icon again.
            self._schedule_ready_icon_memory_load(ready_for_view)
        if retained_icon_index_complete:
            self.logger.event(
                "warm_icon_state_reused_after_view_change",
                packages=len(self.items),
                view="all-packages" if all_packages else "updates",
            )
            self._schedule_background_icon_sweep(restart=True, delay_ms=0)
        else:
            self._start_warm_icon_cache_restore()
        if not self.items and not all_packages and self._scan_results_current:
            checked_time = self._last_scan_completed_at or dt.datetime.now().astimezone()
            checked_short = clock_display_time(checked_time, twelve_hour=True)
            self._empty_state_message = f"✓ Everything is up to date\nChecked {checked_short}"
        else:
            self._empty_state_message = ""
        if self._scan_active and not (self.busy and self._busy_kind == "update"):
            self._refresh_scan_summary_counts()
        elif self.busy:
            view_name = "All packages" if all_packages else "Updates"
            retained = f" • {len(self.items)} retained package(s)" if self.items else ""
            activity = self._activity_base.strip() or "Background operation"
            self.summary_var.set(f"{view_name} • {activity}{retained}")
        else:
            self._refresh_scan_summary_counts()
        self._update_empty_state()

    def _scan_view_item(
        self,
        key: str,
        *,
        prefer_all_packages: bool | None = None,
    ) -> UpdateItem | None:
        """Find a model row without coupling an operation to the visible catalog."""

        if prefer_all_packages is None:
            view_order = (self._last_scan_all_packages, not self._last_scan_all_packages)
        else:
            view_order = (prefer_all_packages, not prefer_all_packages)
        for all_packages in view_order:
            if item := self._scan_view_items[all_packages].get(key):
                return item
        return None

    def _set_scan_view_item_status(self, key: str, status: str) -> UpdateItem | None:
        """Mirror transient operation status to every catalog containing the package."""

        matches: list[UpdateItem] = []
        seen: set[int] = set()
        active = getattr(self, "_active_operation_items", {}).get(key)
        if active is not None:
            active.status = status
        for catalog in (self._scan_view_items[False], self._scan_view_items[True], self.items):
            item = catalog.get(key)
            if item is None or id(item) in seen:
                continue
            seen.add(id(item))
            item.status = status
            matches.append(item)
        visible = self.items.get(key)
        if visible is not None:
            self._refresh_item_row(visible)
            return visible
        return matches[0] if matches else None

    def _refresh_scan_summary_counts(self) -> None:
        admin_count = sum(item.requires_admin for item in self.items.values())
        selected_count = sum(item.selected for item in self.items.values())
        pending_count = sum(
            item.provider == WingetProvider.key
            and item.applicability_prediction == PREDICTION_PENDING
            for item in self.items.values()
        )
        checked_time = self._last_scan_completed_at or dt.datetime.now().astimezone()
        checked_at = clock_display_time(checked_time, twelve_hour=True)
        duration_fragment = (
            f" • scanned in {self._last_scan_duration_seconds:.1f}s"
            if self._last_scan_duration_seconds > 0
            else ""
        )
        expected_count = len(self._scan_expected_provider_keys)
        current_count = len(
            self._scan_current_provider_keys.intersection(
                self._scan_expected_provider_keys
            )
        )
        if self._scan_active and expected_count:
            if (
                self._active_scan_origin == "post-update-verification"
                and self._verification_results
                and self._post_update_refresh_outcomes
            ):
                self.summary_var.set(
                    f"Attempted packages: {self._post_update_refresh_summary()} • "
                    f"{current_count}/{expected_count} providers current • refreshing"
                )
                self._refresh_update_button_readiness()
                return
            noun = "package(s)" if self._last_scan_all_packages else "retained update(s)"
            self.summary_var.set(
                f"{len(self.items)} {noun} • {current_count}/{expected_count} providers "
                "current • refreshing"
            )
            self._refresh_update_button_readiness()
            return
        provisional_visible = bool(
            self._provisional_inventory_keys.intersection(self.items)
        )
        incomplete_inventory = bool(
            expected_count and current_count < expected_count and self._last_scan_completed_at
        )
        if self._last_scan_all_packages and (provisional_visible or incomplete_inventory):
            if self._last_scan_completed_at is None:
                saved_fragment = (
                    " • saved "
                    + clock_display_time(
                        self._provisional_inventory_scanned_at,
                        twelve_hour=True,
                    )
                    if self._provisional_inventory_scanned_at is not None
                    else ""
                )
                freshness = f"previous inventory • awaiting refresh{saved_fragment}"
            elif expected_count:
                freshness = (
                    f"{current_count}/{expected_count} providers current • refresh incomplete"
                )
            else:
                freshness = "previous inventory • refresh needed"
            self.summary_var.set(f"{len(self.items)} package(s) • {freshness}")
            self._refresh_update_button_readiness()
            return
        if self._last_scan_all_packages:
            self.summary_var.set(
                f"{len(self.items)} package(s) • {admin_count} machine-scope"
                f"{duration_fragment} • checked {checked_at}"
            )
        else:
            pending_fragment = f" • {pending_count} checking details" if pending_count else ""
            hold_summary = attempt_hold_scan_summary(
                self.settings.data,
                {item.candidate_key for item in self.items.values()},
            )
            active_holds = int(hold_summary["active_count"])
            stale_holds = int(hold_summary["stale_count"])
            hold_fragment = ""
            if active_holds or stale_holds:
                hold_fragment = f" • {active_holds} held"
                if stale_holds:
                    hold_fragment += f", {stale_holds} stale"
            delta_labels = (
                ("new", "new"),
                ("resolved", "resolved"),
                ("target_changed", "target changed"),
            )
            delta_parts = [
                f"{self._last_scan_delta[key]} {label}"
                for key, label in delta_labels
                if self._last_scan_delta.get(key)
            ]
            delta_fragment = f" • {', '.join(delta_parts)}" if delta_parts else ""
            machine_fragment = (
                "no machine-scope updates"
                if not admin_count
                else f"{admin_count} machine-scope • direct administrator process"
                if self.process_is_admin
                else f"{admin_count} machine-scope • one UAC batch"
            )
            self.summary_var.set(
                f"{len(self.items)} update(s) • {selected_count} selected • "
                f"{machine_fragment}{pending_fragment}{hold_fragment}"
                f"{duration_fragment}{delta_fragment} • "
                f"checked {checked_at}"
            )
        self._refresh_update_button_readiness()

    def _start_winget_enrichment(self) -> None:
        provider = self.providers.get(WingetProvider.key)
        if not isinstance(provider, WingetProvider):
            return
        candidates = [
            item
            for item in self._scan_view_items[False].values()
            if item.provider == WingetProvider.key
            and item.applicability_prediction == PREDICTION_PENDING
        ]
        if not candidates:
            self._winget_enrichment_active = False
            return
        self._enrichment_generation += 1
        generation = self._enrichment_generation
        self._winget_enrichment_active = True
        self._append_log(
            f"WinGet detail checks started for {len(candidates)} package(s)",
            show_in_ui=False,
        )
        threading.Thread(
            target=self._winget_enrichment_worker,
            args=(generation, candidates),
            daemon=True,
        ).start()

    def _winget_enrichment_worker(self, generation: int, candidates: Sequence[UpdateItem]) -> None:
        provider = self.providers.get(WingetProvider.key)
        if not isinstance(provider, WingetProvider):
            return

        def enrich(item: UpdateItem) -> tuple[UpdateItem, str]:
            operation_lock = self._provider_operation_locks[WingetProvider.key]
            acquired = False
            try:
                while generation == self._enrichment_generation and not self._closing:
                    if operation_lock.acquire(timeout=0.1):
                        acquired = True
                        break
                if not acquired or generation != self._enrichment_generation:
                    return dataclasses.replace(item), "superseded by a newer scan"
                return provider.preflight_item(dataclasses.replace(item)), ""
            except Exception as exc:
                fallback = set_applicability_prediction(
                    dataclasses.replace(item),
                    PREDICTION_UNKNOWN,
                    confidence="low",
                    source="background-winget-show",
                    reasons=[
                        f"background WinGet manifest check failed: {type(exc).__name__}: {exc}"
                    ],
                    classification=CLASS_MANUAL_REVIEW,
                    status="Review - manifest unavailable",
                )
                return fallback, f"{type(exc).__name__}: {exc}"
            finally:
                if acquired:
                    operation_lock.release()

        max_workers = min(2, max(1, len(candidates)))
        with concurrent.futures.ThreadPoolExecutor(max_workers=max_workers) as executor:
            futures = [executor.submit(enrich, item) for item in candidates]
            for future in concurrent.futures.as_completed(futures):
                enriched, error = future.result()
                self.events.put(("winget_enriched", (generation, enriched, error)))
        self.events.put(("winget_enrichment_done", generation))

    def _apply_winget_enrichment(self, generation: int, enriched: UpdateItem, error: str) -> None:
        if generation != self._enrichment_generation:
            return
        update_items = self._scan_view_items[False]
        current = update_items.get(enriched.key)
        if current is None:
            return
        if enriched.key in self._selection_touched_keys:
            enriched.selected = current.selected
        else:
            enriched.selected = self._item_is_recommended_selectable(enriched)
        update_items[enriched.key] = enriched
        if not self._last_scan_all_packages:
            self.items = update_items
            self._refresh_item_row(enriched)
            self._refresh_scan_summary_counts()
        for listener in tuple(getattr(self, "_details_refinement_listeners", ())):
            with contextlib.suppress(self.tk.TclError):
                listener(enriched.key)
        self.logger.event(
            "winget_enrichment_finished",
            candidate_key=enriched.candidate_key,
            item=item_diagnostic_fields(enriched),
            error=error,
            selected_preserved=enriched.key in self._selection_touched_keys,
        )

    def _finish_winget_enrichment(self, generation: int) -> None:
        if generation != self._enrichment_generation:
            return
        self._winget_enrichment_active = False
        pending = sum(
            item.provider == WingetProvider.key
            and item.applicability_prediction == PREDICTION_PENDING
            for item in self._scan_view_items[False].values()
        )
        if pending:
            self._append_log(
                f"WinGet detail checks finished with {pending} still pending",
                show_in_ui=False,
            )
        else:
            self._append_log("WinGet detail checks finished", show_in_ui=False)
        if not self._last_scan_all_packages:
            self._refresh_scan_summary_counts()
        self._apply_pending_retry_selection()
        self._schedule_idle_date_sleuth()

    def _apply_pending_retry_selection(self) -> None:
        candidate_keys = self._pending_retry_selection_candidate_keys
        if not candidate_keys or self._scan_active or self._winget_enrichment_active:
            return
        update_items = self._scan_view_items[False]
        selected: list[UpdateItem] = []
        for item in update_items.values():
            item.selected = False
            if item.candidate_key in candidate_keys and self._item_is_bulk_selectable(item):
                item.selected = True
                selected.append(item)
        self._pending_retry_selection_candidate_keys.clear()
        self._selection_touched_keys.update(item.key for item in selected)
        if self._last_scan_all_packages:
            self._show_scan_view(False)
        else:
            self.items = update_items
            self._rebuild_tree()
            self._refresh_scan_summary_counts()
        self._refresh_secondary_actions_menu()
        self.logger.event(
            "retry_failed_rescan_finished",
            requested_count=len(candidate_keys),
            selected_count=len(selected),
            selected_candidate_keys=sorted(item.candidate_key for item in selected),
            automatic_update_started=False,
        )
        if selected:
            self._notify_user(
                f"Selected {len(selected)} retry candidate(s) after a fresh scan. "
                "Review them, then click Update selected when ready.",
                summary=f"{len(selected)} retry candidate(s) selected; review before updating",
            )
        else:
            self._notify_user(
                "The fresh scan found no previously failed candidate that is now eligible "
                "for an ordinary update.",
                summary="No retry candidate is currently eligible",
            )

    def _post_update_refresh_summary(self) -> str:
        total = len(self._verification_results)
        outcomes = self._post_update_refresh_outcomes
        checked = sum(key in outcomes for key in self._verification_results)
        resolved = sum(value == "resolved" for value in outcomes.values())
        still_pending = sum(value == "still-pending" for value in outcomes.values())
        successor = sum(value == "successor" for value in outcomes.values())
        target_changed = sum(value == "target-changed" for value in outcomes.values())
        restart_pending = sum(value == "restart-pending" for value in outcomes.values())
        unverified = sum(value == "unverified" for value in outcomes.values())
        return (
            f"{checked}/{total} attempted checked • {resolved} no longer offered • "
            f"{still_pending} still offered • {successor} newer offer(s) • "
            f"{target_changed} changed target(s) • "
            f"{restart_pending} awaiting restart • {unverified} unverified"
        )

    def _apply_post_update_provider_updates(
        self,
        generation: int,
        provider_key: str,
        provider_label: str,
        updates: Sequence[UpdateItem],
        update_error: str,
        duration_seconds: float,
    ) -> None:
        """Publish the touched provider's authoritative update slice without blocking it."""

        if (
            self._closing
            or generation != self._active_scan_generation
            or not self._scan_active
            or self._active_scan_origin != "post-update-verification"
        ):
            return
        expected = {
            key: record
            for key, record in self._verification_results.items()
            if str(record.get("item", {}).get("provider", "")) == provider_key
        }
        if not expected:
            return
        reconciliation = reconcile_verification_results(
            expected,
            updates,
            {provider_key} if update_error else set(),
        )
        unavailable_status = (
            "Provider is disabled or unavailable — inventory refreshing"
            if update_error == "provider is disabled or unavailable"
            else ""
        )
        status_groups = (
            (
                "no_longer_offered",
                "resolved",
                "No longer offered after attempt — inventory refreshing",
            ),
            ("successor_offered", "successor", ""),
            ("target_changed", "target-changed", ""),
            ("restart_pending", "restart-pending", ""),
            ("still_pending", "still-pending", ""),
            (
                "unverified",
                "unverified",
                unavailable_status,
            ),
        )
        for group, outcome, fixed_status in status_groups:
            for record in reconciliation[group]:
                key = str(record["key"])
                self._post_update_refresh_outcomes[key] = outcome
                status = fixed_status or str(
                    reconciliation["status_by_key"].get(key, "Attempt checked")
                ) + " — inventory refreshing"
                refreshed = self._set_scan_view_item_status(key, status)
                if refreshed is not None:
                    refreshed.selected = False
        for key in expected:
            for catalog in (*self._scan_view_items.values(), self.items):
                if key in catalog:
                    catalog[key].selected = False
        summary = self._post_update_refresh_summary()
        self.summary_var.set(f"Attempted packages: {summary} • inventory refreshing")
        self._activity_base = (
            f"Attempted packages checked through {provider_label}; "
            "refreshing installed-package inventory"
        )
        self._append_log(
            f"Attempted-package refresh — {provider_label}: "
            f"{len(reconciliation['no_longer_offered'])} no longer offered, "
            f"{len(reconciliation['still_pending'])} still offered, "
            f"{len(reconciliation['successor_offered'])} newer offer(s), "
            f"{len(reconciliation['target_changed'])} changed target(s), "
            f"{len(reconciliation['restart_pending'])} awaiting restart, "
            f"{len(reconciliation['unverified'])} unverified "
            f"({duration_seconds:.1f}s); inventory continues"
        )
        self.logger.event(
            "post_update_provider_updates_painted",
            update_id=self._verification_update_id,
            scan_generation=generation,
            provider=provider_key,
            provider_label=provider_label,
            duration_seconds=duration_seconds,
            update_error=update_error,
            no_longer_offered=reconciliation["no_longer_offered"],
            still_pending=reconciliation["still_pending"],
            successor_offered=reconciliation["successor_offered"],
            target_changed=reconciliation["target_changed"],
            restart_pending=reconciliation["restart_pending"],
            contradicted_success=reconciliation["contradicted_success"],
            installed_state_changed=reconciliation["installed_state_changed"],
            unverified=reconciliation["unverified"],
        )

    def _finish_post_update_verification(
        self,
        failed_provider_keys: set[str],
        unavailable_provider_keys: set[str] | None = None,
    ) -> None:
        expected = self._verification_results
        update_id = self._verification_update_id
        update_items = self._scan_view_items[False]
        reconciliation = reconcile_verification_results(
            expected, update_items, failed_provider_keys,
            tuple(self._scan_view_items[True].values()),
        )
        still_pending = reconciliation["still_pending"]
        no_longer_offered = reconciliation["no_longer_offered"]
        successor_offered = reconciliation["successor_offered"]
        target_changed = reconciliation["target_changed"]
        restart_pending = reconciliation["restart_pending"]
        unverified = reconciliation["unverified"]
        contradicted_success = reconciliation["contradicted_success"]
        unavailable_provider_keys = set(unavailable_provider_keys or ())
        verification_holds: list[dict[str, Any]] = []
        for record in contradicted_success:
            key = str(record["key"])
            result = dict(expected.get(key, {}).get("result", {}))
            result.update(
                {
                    "key": key,
                    "success": False,
                    "outcome": "verification-conflict",
                    "classification": CLASS_VERIFICATION_CONFLICT,
                    "status_hint": (
                        str(record.get("verification_conflict_reason", ""))
                        or "The package manager reported success, but a fresh read-only "
                        "scan still offered this same exact update."
                    ),
                }
            )
            verification_holds.append(result)
        for record in reconciliation["installed_state_changed"]:
            key = str(record["key"])
            result = dict(expected.get(key, {}).get("result", {}))
            result.update(
                {
                    "key": key,
                    "success": False,
                    "outcome": "verification-state-change",
                    "classification": CLASS_MANUAL_REVIEW,
                    "status_hint": (
                        "The installed version changed during the attempt, but a fresh "
                        "read-only scan still offered the same target. Review the package "
                        "details before deliberately retrying."
                    ),
                }
            )
            verification_holds.append(result)
        if verification_holds:
            # Reuse the ordinary exact-candidate hold path. This records the conflict
            # without guessing which side is stale or changing provider-owned metadata.
            self._remember_attempt_outcomes(verification_holds)
        for key, status in reconciliation["status_by_key"].items():
            if key in update_items:
                update_items[key].status = status
                update_items[key].selected = False
        for record in reconciliation["unverified"]:
            key = str(record["key"])
            if key in update_items:
                provider_key = str(record.get("item", {}).get("provider", ""))
                update_items[key].status = (
                    "Provider is disabled or unavailable"
                    if provider_key in unavailable_provider_keys
                    else str(
                        reconciliation["status_by_key"].get(
                            key, "Verification inconclusive — provider scan failed"
                        )
                    )
                )
                update_items[key].selected = False
        original_package_history = dict(
            self.settings.data.get("package_history", {})
        )
        package_history = dict(original_package_history)
        verified_service_count = 0
        for record in (*no_longer_offered, *successor_offered):
            key = str(record.get("key", ""))
            result = expected.get(key, {}).get("result", {})
            item_data = record.get("item", {})
            if not (
                isinstance(result, Mapping)
                and isinstance(item_data, Mapping)
                and result.get("success")
                and str(result.get("outcome", ""))
                in {"updated", "updated-with-warnings"}
                and bool(record.get("installed_verified"))
                and not result.get("needs_reboot")
            ):
                continue
            package_history = remember_package_history_event(
                package_history,
                provider=str(item_data.get("provider", "")),
                package_id=str(item_data.get("package_id", "")),
                name=str(item_data.get("name", "")),
                action="update",
                observed_at=str(result.get("finished_at") or utc_now_iso()),
                version=str(item_data.get("available_version", "")),
                scope=str(item_data.get("scope", "")),
                source=str(item_data.get("source", "")),
            )
            verified_service_count += 1
        if package_history != original_package_history:
            self.settings.data["package_history"] = package_history
            try:
                self.settings.save()
                self.logger.event(
                    "package_history_updated",
                    update_id=update_id,
                    remembered_count=len(package_history),
                    verified_service_count=verified_service_count,
                    source="post-update-verification",
                )
            except OSError as exc:
                self.settings.data["package_history"] = original_package_history
                self._append_log(
                    f"Could not remember verified WinDevPilot update history: {exc}",
                    show_in_ui=False,
                )
        self._verification_results = {}
        self._confirmed_attempt_items = {}
        self._verification_update_id = ""
        self._post_update_refresh_outcomes.clear()
        self._active_operation_items.clear()
        self._active_operation_results.clear()
        if not self._last_scan_all_packages:
            self.items = update_items
            self._rebuild_tree()
        self.logger.event(
            "post_update_verification_finished",
            update_id=update_id,
            no_longer_offered=no_longer_offered,
            still_pending=still_pending,
            successor_offered=successor_offered,
            target_changed=target_changed,
            restart_pending=restart_pending,
            contradicted_success=contradicted_success,
            installed_state_changed=reconciliation["installed_state_changed"],
            unverified=unverified,
            unavailable_provider_keys=sorted(unavailable_provider_keys),
        )
        # A newer batch may have started while this read-only verification ran.
        # Retire only the operation identity that this scan actually reconciled.
        if self.active_update_id == update_id:
            self.active_update_id = ""
        self._append_log(
            "Verification finished: "
            f"{len(no_longer_offered)} no longer offered, "
            f"{len(still_pending)} still offered after attempt, "
            f"{len(successor_offered)} newer offer(s), "
            f"{len(target_changed)} changed target(s), "
            f"{len(restart_pending)} awaiting restart, {len(unverified)} unverified"
        )
        if not self._last_scan_all_packages:
            self.summary_var.set(
                f"Verification: {len(no_longer_offered)} no longer offered • "
                f"{len(still_pending)} still offered after attempt • "
                f"{len(successor_offered)} newer offer(s) • "
                f"{len(target_changed)} changed target(s) • "
                f"{len(restart_pending)} awaiting restart • {len(unverified)} unverified"
            )
        if contradicted_success:
            names = ", ".join(
                str(record["item"].get("name", record["item"].get("package_id", "?")))
                for record in contradicted_success[:5]
            )
            self._notify_user(
                f"Verification still sees {len(contradicted_success)} update(s) that "
                f"the package manager reported as successful: {names}. "
                "Those exact candidates are held from ordinary retries until provider "
                "metadata changes or you deliberately use Test once.",
                level="warning",
                summary="Verification contradiction: exact updates held",
            )

    def _filter_rank(
        self,
        item: UpdateItem,
        query: str | None = None,
    ) -> tuple[int, int]:
        query = self.search_var.get().strip() if query is None else query
        if not query:
            return (0, 0)
        if ":" in query:
            query, filters = parse_package_filter(query)
            if filters:
                holds = self.settings.data.get("attempt_holds", {}) if ("is", "held") in filters else {}
                if not package_filter_matches(item, filters, holds if isinstance(holds, Mapping) else {}):
                    return (999, 999_999)
                if not query:
                    return (0, 0)
        provider_label = self._provider_display_label(item)
        return search_match_rank(
            query,
            (
                (0, item.name),
                (1, item.package_id),
                (2, provider_label),
                (2, item.provider),
                (3, item.current),
                (3, item.available),
                (3, item.source),
                (3, item.scope),
                (3, item.status),
                (3, item.classification),
                (3, item.guidance),
                (3, item.applicability_prediction),
                (3, item.predicted_hresult),
                (3, " ".join(item.prediction_reasons)),
                (3, self._run_as_label(item)),
            ),
        )

    def _matches_filter(self, item: UpdateItem, query: str | None = None) -> bool:
        return self._filter_rank(item, query)[0] < 999

    def _filter_match_rank(
        self,
        item: UpdateItem,
        query: str | None = None,
    ) -> tuple[int, int]:
        return self._filter_rank(item, query)

    @staticmethod
    def _item_is_actionable(item: UpdateItem) -> bool:
        if item.classification == CLASS_INVENTORY_ONLY:
            return False
        if item.provider == WingetProvider.key and item.status == "Pinned — left unchanged":
            return False
        return not (item.provider == "winget" and item.scope not in {"user", "machine"})

    @classmethod
    def _item_is_bulk_selectable(cls, item: UpdateItem) -> bool:
        return (
            cls._item_is_actionable(item)
            and item.applicability_prediction in {"", PREDICTION_ORDINARY}
            and item.status not in BULK_SELECTION_REVIEW_STATUSES
            and not item.status.startswith("Held after ")
            and item.classification not in NON_BULK_CLASSIFICATIONS
        )

    @classmethod
    def _item_is_recommended_selectable(cls, item: UpdateItem) -> bool:
        return cls._item_is_bulk_selectable(item) and item.provider != PipProvider.key

    @classmethod
    def _item_needs_review(cls, item: UpdateItem) -> bool:
        return cls._item_is_actionable(item) and not cls._item_is_bulk_selectable(item)

    def _installed_service_date_evidence(self, item: UpdateItem) -> InstalledServiceDate:
        return installed_service_date_evidence(
            item,
            self.settings.data,
            getattr(self, "_installation_observations", {}),
        )

    @staticmethod
    def _winget_needs_manifest_enrichment(
        item: UpdateItem, providers: Mapping[str, Provider]
    ) -> bool:
        provider = providers.get(WingetProvider.key)
        return isinstance(provider, WingetProvider) and provider._should_preflight_item(item)

    def _mark_item_enrichment_pending(self, item: UpdateItem) -> UpdateItem:
        if (
            item.provider == WingetProvider.key
            and item.classification == CLASS_SIMPLE_UPGRADE
            and self._winget_needs_manifest_enrichment(item, self.providers)
        ):
            item.selected = False
            return set_applicability_prediction(
                item,
                PREDICTION_PENDING,
                confidence="pending",
                source="inventory",
                reasons=["WinGet manifest details are being checked in the background"],
                classification=CLASS_SIMPLE_UPGRADE,
                status="Checking details…",
            )
        return item

    def _run_as_label(self, item: UpdateItem) -> str:
        if item.provider == "winget" and item.scope not in {"user", "machine"}:
            return "Scope unresolved"
        if item.provider == MICROSOFT_STORE_PROVIDER_KEY:
            return "Current Store account"
        if self.process_is_admin:
            return "Current admin"
        return "Admin via UAC" if item.requires_admin else "Current account"

    def _provider_display_label(self, item: UpdateItem) -> str:
        return installed_channel_display_label(
            item,
            self.providers[item.provider].label,
        )

    def _sort_value(self, item: UpdateItem, column: str) -> Any:
        if column == "installed_date":
            return self._installed_service_date_evidence(item).date
        values: dict[str, Any] = {
            "selected": item.selected,
            "name": item.name.casefold(),
            "id": item.package_id.casefold(),
            "current": item.current.casefold(),
            "available": item.available.casefold(),
            "provider": self._provider_display_label(item).casefold(),
            "status": item.status.casefold(),
        }
        return values[column]

    def _installed_date_sort_value(self, item: UpdateItem, newest_first: bool) -> tuple[Any, ...]:
        """Keep unknowns last and use the finest credible time behind the compact cell."""

        evidence = self._installed_service_date_evidence(item)
        if not evidence.date:
            return (1, 0, item.name.casefold(), item.key)
        instant = wall_clock_order_key(evidence.timestamp or evidence.window_end)
        day = dt.date.fromisoformat(evidence.date).toordinal()
        return (
            0,
            -day if newest_first else day,
            -instant if newest_first else instant,
            item.name.casefold(),
            item.key,
        )

    def _has_real_icon_source(self, item: UpdateItem) -> bool:
        icon_size = max(12, self.visuals.px(PACKAGE_ICON_SIZE_DIP))
        memory_key = (item.key, icon_size, self.palette["mode"])
        if memory_key in self._package_icon_images:
            return True
        return memory_key in self._package_icon_ready

    def _icon_color_descriptor(self, item: UpdateItem) -> tuple:
        """Describe displayed artwork from memory only; never discover a source on a click."""
        size = max(12, self.visuals.px(PACKAGE_ICON_SIZE_DIP))
        if preferred_vector_style(item) or not self._has_real_icon_source(item):
            return (0, fallback_vector_style(item), size)
        memory_key = (item.key, size, self.palette["mode"])
        catalog_path = self._icon_catalog_list_display_paths.get((item.key, size), "")
        return (1, item.key, size, self.palette["mode"], item.current,
                catalog_path,
                self._item_icon_source_cache.get(item.key),
                "" if catalog_path else str(self._package_icon_images.get(memory_key, "")))

    def _icon_sort_value(self, item: UpdateItem) -> Any:
        descriptor = self._icon_color_descriptor(item)
        previous, color = self._icon_sort_colors.get(item.key, (None, (2, 0.0, 0.0)))
        if previous != descriptor:
            color = (2, 0.0, 0.0)
        group = descriptor[0] if self._icon_sort_grouped else 0
        return (group, *color, item.name.casefold(), item.package_id.casefold(), item.key)

    def _refresh_sort_headings(self, active_column: str | None = None, marker: str = "") -> None:
        self.tree.heading("#0", text=marker.strip() if active_column == "#0" else "Art")
        for heading_column, label in self._tree_headings.items():
            heading_marker = marker if heading_column == active_column else ""
            self.tree.heading(heading_column, text=f"{label}{heading_marker}")

    def _sort_by_icon_column(self) -> None:
        self._icon_sort_grouped = not self._icon_sort_grouped if self._icon_sort_active else False
        self._icon_sort_active = True
        self._refresh_sort_headings("#0", " △△" if self._icon_sort_grouped else " ▲")
        self._rebuild_tree()

    def _schedule_icon_sort_refresh(self) -> None:
        """Accumulate artwork changes without rebuilding or interrupting a gesture."""
        if not self._icon_sort_active or self._closing:
            return
        self._icon_sort_refresh_pending = True
        if getattr(self, "_icon_sort_refresh_after_id", None) is None:
            self._icon_sort_refresh_after_id = self.root.after(250, self._apply_pending_icon_sort)

    def _apply_pending_icon_sort(self) -> None:
        self._icon_sort_refresh_after_id = None
        if not self._icon_sort_active or self._closing:
            self._icon_sort_refresh_pending = False
            return
        # List artwork determines the colors. Details lookahead must not delay
        # this commit, and color sorting must not pause icon acquisition itself.
        unsettled = any(getattr(self, name, None) for name in (
            "_cache_clear_inflight", "_scan_active", "_icon_background_sweep_active", "_icon_catalog_decode_queue",
            "_icon_memory_load_queue", "_icon_color_working", "_package_gallery_drag",
            "_package_gallery_motion_after_id", "_package_list_drag", "_package_list_motion_after_id",
        ))
        quiet_until = max(getattr(self, "_icon_scroll_quiet_until", 0.0),
                          getattr(self, "_details_idle_quiet_until", 0.0))
        if (unsettled or not getattr(self, "_icon_catalog_loaded", True)
                or time.monotonic() < quiet_until or self._native_window_interaction_active()
                or any(not key[0].startswith("details:") for key in self._icon_prepare_inflight)):
            self._schedule_icon_sort_refresh()
            return
        if self._start_icon_priority_resolution():
            self._schedule_icon_sort_refresh()
            return
        self._icon_sort_refresh_pending = False
        # Keep the package at the top of the gallery visible after the one reorder.
        anchor = None
        if getattr(self, "_package_gallery_mode", False):
            keys, columns, _cell, row = self._package_gallery_geometry
            index = max(0, int(self._package_gallery_canvas.canvasy(0) // row) * columns)
            if index < len(keys):
                anchor = keys[index]
        self._rebuild_tree()
        if anchor is not None and anchor in self._tree_display_order:
            self._package_gallery_zoom_anchor = self._tree_display_order.index(anchor)

    def _start_icon_priority_resolution(self) -> bool:
        if self._icon_color_working is not None or self._closing or getattr(self, "_cache_clear_inflight", False):
            return False
        candidates = []
        for item in self.items.values():
            if not self._matches_filter(item):
                continue
            descriptor = self._icon_color_descriptor(item)
            if self._icon_sort_colors.get(item.key, (None, None))[0] != descriptor:
                blob = self._icon_catalog_blobs.get(descriptor[5]) if descriptor[0] else None
                candidates.append((dataclasses.replace(item), descriptor, blob))
        if not candidates:
            return False
        self._icon_resolution_generation += 1
        generation = self._icon_resolution_generation
        self._icon_color_working = generation
        threading.Thread(
            target=self._icon_priority_resolution_worker,
            args=(generation, candidates), name="wdp-icon-colors", daemon=True,
        ).start()
        return True

    def _icon_priority_resolution_worker(
        self, generation: int, candidates: Sequence[tuple],
    ) -> None:
        results, shared = {}, {}
        persisted = load_icon_color_cache()
        new_colors = {}
        for item, descriptor, png in candidates:
            if generation != self._icon_resolution_generation or self._closing:
                break
            try:
                if descriptor not in shared:
                    if descriptor[0] == 0:
                        png = cached_vector_bitmap(descriptor[1], descriptor[2]).png
                    elif png is None:
                        path_text, source = descriptor[5:7]
                        if not path_text and source is not None:
                            raw_path = self._package_icon_cache_path(item, source, descriptor[2])
                            path_text = str(self._display_icon_cache_path(raw_path, descriptor[2]))
                        if path_text:
                            with Path(path_text).open("rb") as stream:
                                png = stream.read(ICON_CATALOG_SINGLE_BLOB_MAX_BYTES+1)
                    color = (2, 0.0, 0.0)
                    if png and len(png) <= ICON_CATALOG_SINGLE_BLOB_MAX_BYTES:
                        digest = hashlib.sha256(png).hexdigest()
                        color = persisted.get(digest)
                        if color is None:
                            color = icon_rainbow_sort_key(png)
                            if color[0] != 2:
                                persisted[digest] = new_colors[digest] = color
                    shared[descriptor] = color
                color = shared[descriptor]
            except (OSError, ValueError, struct.error, zlib.error):
                color = (2, 0.0, 0.0)  # Unreadable color is not proof that artwork is generated.
            results[item.key] = (descriptor, color)
        if new_colors:
            try:
                with self._icon_catalog_write_lock:
                    if generation == self._icon_resolution_generation and not self._closing:
                        # One small atomic write per batch, never per pixel/icon or sort click.
                        atomic_write_text(icon_cache_dir() / "appicon-colors-v7.json",
                                          json.dumps(dict(list(persisted.items())[-10000:]), separators=(",", ":")))
            except OSError:
                pass  # Color sorting still works when the graphics cache is read-only.
        self.events.put(("icon_resolution_done", (generation, results)))

    def _finish_icon_priority_resolution(
        self, generation: int, results: dict,
    ) -> None:
        if self._icon_color_working == generation:
            self._icon_color_working = None
        if generation == self._icon_resolution_generation:
            self._icon_sort_colors.update({
                key: value for key, value in results.items()
                if key in self.items and self._icon_color_descriptor(self.items[key]) == value[0]
            })
            self._icon_sort_colors = {key: value for key, value in self._icon_sort_colors.items() if key in self.items}
        if generation == self._icon_resolution_generation:
            self._schedule_icon_sort_refresh()

    def _sort_by(self, column: str, *, force_reverse: bool | None = None) -> None:
        if column not in self._tree_headings:
            return
        self._icon_sort_active = False
        self._icon_sort_refresh_pending = False
        self._cancel_after_id("_icon_sort_refresh_after_id")
        self._icon_resolution_generation += 1
        reverse = bool(force_reverse)
        if force_reverse is None and self._sort_state and self._sort_state[0] == column:
            reverse = not self._sort_state[1]
        self._sort_state = (column, reverse)
        self._refresh_sort_headings(column, " ▼" if reverse else " ▲")
        self._rebuild_tree()

    def _tree_select_all_shortcut(self, _event: Any) -> str:
        self.select_all()
        return "break"

    def _tree_control_click(self, event: Any) -> str | None:
        """Offer a quiet power-user shortcut for newest-install-first sorting."""

        if self.tree.identify_region(event.x, event.y) != "heading":
            return None
        column = self._tree_display_column_name(self.tree.identify_column(event.x))
        if column != "installed_date":
            return None
        self._sort_by("installed_date", force_reverse=True)
        return "break"

    def _tree_display_column_name(self, display_id: str) -> str:
        """Map Tk's visible #N identifier back to the stable logical column name."""

        try:
            display_index = int(display_id.removeprefix("#")) - 1
            display_columns = tuple(self.tree.cget("displaycolumns"))
            if display_columns == ("#all",):
                display_columns = self._tree_columns
            return str(display_columns[display_index])
        except (IndexError, TypeError, ValueError):
            return ""

    def _schedule_rebuild_tree(self, *, prime_cached_first_paint: bool = False) -> None:
        self._rebuild_prime_cached_first_paint = (
            self._rebuild_prime_cached_first_paint or prime_cached_first_paint
        )
        if self._rebuild_after_id is None:
            self._rebuild_after_id = self.root.after(120, self._run_scheduled_rebuild_tree)

    def _run_scheduled_rebuild_tree(self) -> None:
        self._rebuild_after_id = None
        if self._native_window_interaction_active():
            self._rebuild_after_id = self.root.after(
                WINDOW_DRAG_BUSY_ANIMATION_POLL_MS,
                self._run_scheduled_rebuild_tree,
            )
            return
        prime_cached_first_paint = self._rebuild_prime_cached_first_paint
        self._rebuild_prime_cached_first_paint = False
        started = time.perf_counter()
        self._rebuild_tree(prime_cached_first_paint=prime_cached_first_paint)
        self.logger.event(
            "perf_probe",
            probe="scheduled_rebuild_tree_tk",
            duration_ms=round((time.perf_counter() - started) * 1000.0, 3),
            item_count=len(self.items),
            view="all-packages" if self._last_scan_all_packages else "updates",
            scan_active=self._scan_active,
            logger_queue=self.logger.queue_depth_metrics(),
        )

    def _item_row_values(
        self, item: UpdateItem
    ) -> tuple[str, str, str, str, str, str, str, str]:
        provisional = self._item_inventory_is_provisional(item)
        verified_version = self._early_verified_installed_version(item)
        date = self._installed_service_date_evidence(item)
        return (
            CHECKED_GLYPH if item.selected else UNCHECKED_GLYPH,
            item.name,
            self._display_package_id(item),
            verified_version or ("Checking…" if provisional else item.current),
            verified_version or ("Checking…" if provisional else item.available),
            date.display_text,
            self._provider_display_label(item),
            "Previous inventory" if provisional and not verified_version else self._display_status(item),
        )

    def _early_verified_installed_version(self, item: UpdateItem) -> str:
        for entry in getattr(self, "_active_operation_results", ()):
            if version := verified_winget_installed_version(entry, item):
                return version
        pending = getattr(self, "_verification_results", {}).get(item.key, {})
        return verified_winget_installed_version(pending.get("result", {}), item)

    def _item_inventory_is_provisional(self, item: UpdateItem) -> bool:
        return item.key in getattr(self, "_provisional_inventory_keys", set())

    @staticmethod
    def _display_package_id(item: UpdateItem) -> str:
        """Keep durable portable identity exact internally but compact in the table."""

        if item.provider != PORTABLE_PROVIDER_KEY:
            return item.package_id
        parts = item.package_id.split(".")
        if len(parts) < 3:
            return item.package_id
        kind = parts[1]
        if kind.startswith("generic-"):
            kind = "generic"
        suffix = parts[-1][-8:]
        return f"portable.{kind}…{suffix}"

    @staticmethod
    def _display_status(item: UpdateItem) -> str:
        """Use concise portable wording in the dense table; details retain full evidence."""

        if item.provider != PORTABLE_PROVIDER_KEY:
            return item.status
        replacements = (
            ("Portable app", "Portable"),
            ("verified PAF layout", "PAF verified"),
            ("high-confidence local evidence", "High confidence"),
            ("WinGet catalog ", "Catalog "),
            ("Release clue ", "Release "),
            ("catalog version unavailable", "No release version"),
            ("removable file", "Can remove file"),
            ("removable folder", "Can remove folder"),
        )
        status = item.status
        for verbose, compact in replacements:
            status = status.replace(verbose, compact)
        return status

    def _refresh_item_row(self, item: UpdateItem) -> None:
        row_exists = self.tree.exists(item.key)
        matches_filter = self._matches_filter(item)
        if row_exists != matches_filter:
            self._schedule_rebuild_tree()
            return
        if not row_exists:
            return
        getattr(self, "_tree_row_presentations", {}).pop(item.key, None)
        self.tree.item(
            item.key,
            text="",
            tags=self._row_tags(item),
            values=self._item_row_values(item),
        )
        if self._tree_icon_kind.get(item.key) != "app":
            self._schedule_visible_icon_hydration()
        self._schedule_package_gallery_render()

    def _ordered_visible_items(self, query: str) -> list[UpdateItem]:
        """Filter before column sorting, then apply the stable search-rank overlay."""
        ordered_items = list(self.items.values())
        query_active = bool(query)
        filter_ranks = (
            {item.key: self._filter_match_rank(item, query) for item in ordered_items}
            if query_active
            else {}
        )
        if query_active:
            ordered_items = [item for item in ordered_items if filter_ranks[item.key][0] < 999]
        if self._icon_sort_active:
            if not getattr(self, "_icon_sort_refresh_pending", False) and self._start_icon_priority_resolution():
                self._schedule_icon_sort_refresh()
            if getattr(self, "_icon_sort_refresh_pending", False):
                previous_order = {key: index for index, key in enumerate(getattr(self, "_tree_display_order", ()))}
                ordered_items.sort(key=lambda item: (previous_order.get(item.key, len(previous_order)),
                                                     item.name.casefold(), item.key))
            else:
                ordered_items.sort(key=self._icon_sort_value)
        elif self._sort_state:
            column, reverse = self._sort_state
            if column == "installed_date":
                ordered_items.sort(
                    key=lambda item: self._installed_date_sort_value(item, reverse)
                )
            else:
                ordered_items.sort(
                    key=lambda item: (self._sort_value(item, column), item.key),
                    reverse=reverse,
                )
        if query_active and (self._icon_sort_active or self._sort_state):
            ordered_items.sort(key=lambda item: filter_ranks[item.key])
        elif query_active:
            ordered_items.sort(
                key=lambda item: (
                    filter_ranks[item.key],
                    item.name.casefold(),
                    item.package_id.casefold(),
                    item.key,
                )
            )
        return ordered_items

    def _rebuild_tree(self, *, prime_cached_first_paint: bool = False) -> None:
        self._stop_package_list_motion()
        self._tree_wheel_remainder = 0
        if self._rebuild_after_id is not None:
            self._cancel_after_id("_rebuild_after_id")
        self._hide_tooltip()
        selected_rows = set(self.tree.selection())
        focus_row = self.tree.focus()
        try:
            top_fraction = self.tree.yview()[0]
        except self.tk.TclError:
            top_fraction = 0.0
        displayed_items = self._ordered_visible_items(self.search_var.get().strip())
        icon_size = max(12, self.visuals.px(PACKAGE_ICON_SIZE_DIP))
        palette_mode = self.palette["mode"]
        primed_icons = 0
        prime_duration = 0.0
        if prime_cached_first_paint and displayed_items:
            # A view change used to paint provider markers first, then decode
            # durable cached icons on a later Tk tick. Decode only the target
            # viewport while the old rows remain visible so the replacement
            # rows can contain their final artwork on their first paint.
            row_height = max(1, self.visuals.px(UPDATE_ROW_HEIGHT_DIP))
            visible_count = max(8, int(self.tree.winfo_height() / row_height) + 8)
            start = max(0, int(top_fraction * len(displayed_items)) - 4)
            stop = min(len(displayed_items), start + visible_count)
            prime_started = time.perf_counter()
            for item in displayed_items[start:stop]:
                memory_key = (item.key, icon_size, palette_mode)
                if memory_key in self._package_icon_images:
                    continue
                if memory_key not in self._package_icon_ready:
                    continue
                if self._item_icon_if_ready(item) is not None:
                    primed_icons += 1
            prime_duration = time.perf_counter() - prime_started
        old_order = self.tree.get_children()
        presentations = getattr(self, "_tree_row_presentations", None)
        if presentations is None:
            presentations = self._tree_row_presentations = {}
        desired_order = tuple(item.key for item in displayed_items)
        desired_keys = set(desired_order)
        top_key = old_order[min(len(old_order) - 1, int(top_fraction * len(old_order)))] if old_order else ""
        removed = set(old_order) - desired_keys
        if removed:
            self.tree.delete(*removed)
            for key in removed:
                self._tree_icon_kind.pop(key, None)
                presentations.pop(key, None)
        existing_keys = set(old_order) - removed
        for item in displayed_items:
            memory_key = (item.key, icon_size, palette_mode)
            row_image = self._package_icon_images.get(memory_key)
            row_image = self._presentation_icon(item, row_image, icon_size)
            icon_kind = "app"
            if row_image is None:
                row_image = self._fallback_icon(item, icon_size)
                icon_kind = "provider"
            presentation = dict(text="", image=row_image, tags=self._row_tags(item),
                                values=self._item_row_values(item))
            signature = (presentation["values"], presentation["tags"], str(row_image))
            if item.key not in existing_keys:
                self.tree.insert("", "end", iid=item.key, **presentation)
            elif presentations.get(item.key) != signature:
                self.tree.item(item.key, **presentation)
            presentations[item.key] = signature
            self._tree_icon_kind[item.key] = icon_kind
        if old_order != desired_order:
            self.tree.set_children("", *desired_order)
        if getattr(self, "_tree_display_order", None) != desired_order:
            self._stop_package_gallery_motion()
        self._tree_display_order = desired_order
        retained_selection = selected_rows & desired_keys
        if set(self.tree.selection()) != retained_selection:
            self.tree.selection_set(*retained_selection)
        if focus_row in desired_keys:
            self.tree.focus(focus_row)
        if top_fraction > 0.0:
            with contextlib.suppress(Exception):
                self.tree.yview_moveto(
                    desired_order.index(top_key) / max(1, len(desired_order))
                    if top_key in desired_keys else top_fraction
                )
        if primed_icons:
            self.logger.event(
                "cached_icons_primed_for_first_paint",
                icons=primed_icons,
                duration_seconds=round(prime_duration, 4),
                view="all-packages" if self._last_scan_all_packages else "updates",
            )
        self._update_empty_state()
        if getattr(self, "_package_icon_ready", None):
            self._prioritize_visible_ready_icon_memory_load()
        self._schedule_visible_icon_hydration(
            delay_ms=0 if prime_cached_first_paint else 240,
            restart=prime_cached_first_paint,
        )
        self._refresh_update_button_readiness()
        self._schedule_package_gallery_render()
        self._enqueue_gallery_idle_promotions()
        for listener in tuple(getattr(self, "_details_refinement_listeners", ())):
            with contextlib.suppress(self.tk.TclError):
                listener("")

    def _row_tags(self, item: UpdateItem) -> tuple[str, ...]:
        if item.selected:
            return ("selected",)
        if self._item_needs_review(item):
            return ("review",)
        if item.requires_admin and item.classification != CLASS_INVENTORY_ONLY:
            return ("admin",)
        if item.key == self._hover_row:
            return ("hover",)
        return ()

    def _update_empty_state(self) -> None:
        label = getattr(self, "empty_state_label", None)
        hint_frame = getattr(self, "empty_state_hint_frame", None)
        if label is None:
            return
        message = ""
        hint = ""
        if not self.busy and not self.tree.get_children():
            query = self.search_var.get().strip()
            all_package_matches = 0
            if query and not self._last_scan_all_packages:
                all_package_matches = sum(
                    self._matches_filter(item, query)
                    for item in self._scan_view_items[True].values()
                )
            if query and (self.items or all_package_matches):
                message = "No packages match this filter."
                if all_package_matches:
                    noun = "match" if all_package_matches == 1 else "matches"
                    hint = f" to see {all_package_matches} {noun}."
            else:
                message = self._empty_state_message
        if not message:
            label.place_forget()
            if hint_frame is not None:
                hint_frame.place_forget()
            return
        label.configure(text=message)
        label.place(relx=0.5, rely=0.46, anchor="center")
        label.lift()
        if hint_frame is not None:
            if hint:
                self.empty_state_hint_suffix.configure(text=hint)
                hint_frame.place(
                    relx=0.5,
                    rely=0.46,
                    y=self.visuals.px(34),
                    anchor="center",
                )
                hint_frame.lift()
            else:
                hint_frame.place_forget()

    def _tree_click(self, event: Any) -> None:
        self._tree_wheel_remainder = 0
        region = self.tree.identify_region(event.x, event.y)
        column = self._tree_display_column_name(self.tree.identify_column(event.x))
        row = self.tree.identify_row(event.y)
        if region in {"tree", "cell"} and row:
            self.tree.focus_set()
        if self.busy:
            return
        if region == "cell" and column == "selected" and row in self.items:
            self._toggle_tree_rows_like(row)
            return "break"

    def _tree_double_click(self, event: Any) -> str | None:
        region = self.tree.identify_region(event.x, event.y)
        row = self.tree.identify_row(event.y)
        if region not in {"tree", "cell"} or row not in self.items:
            return None
        self._hide_tooltip()
        self.tree.focus_set()
        self.tree.selection_set(row)
        self.tree.focus(row)
        self.show_item_details(self.items[row], reuse_quick_window=True)
        return "break"

    def _new_context_menu(self, owner: Any) -> Any:
        # Dispose on the next invocation, after the previous popup has completed.
        # Destroying a menu also releases its submenus and registered callbacks.
        previous = getattr(owner, "_wdp_context_menu", None)
        if previous is not None:
            previous.destroy()
        menu = self.tk.Menu(owner, tearoff=False)
        owner._wdp_context_menu = menu
        return menu

    def _tree_context_menu(self, event: Any) -> str:
        return self._show_package_context_menu(self.tree.identify_row(event.y), event, self.tree)

    def _show_package_context_menu(self, row: str, event: Any, owner: Any) -> str:
        """Share package actions and selection rules between list and gallery."""
        if row not in self.items:
            return "break"
        item = self.items[row]
        owner.focus_set()
        if row not in self.tree.selection():
            self.tree.selection_set(row)
        self.tree.focus(row)
        context_rows = tuple(
            str(selected_row)
            for selected_row in self.tree.selection()
            if str(selected_row) in self.items
        )
        context_items = tuple(self.items[selected_row] for selected_row in context_rows)
        all_selected_portables = bool(context_items) and all(
            selected_item.provider == PORTABLE_PROVIDER_KEY
            and bool(selected_item.portable_executable)
            for selected_item in context_items
        )
        self._hide_tooltip()
        menu = self._new_context_menu(owner)
        run_routes = app_run_routes(item)
        run_route = run_routes[0] if len(run_routes) == 1 else None
        containing_target = app_containing_target(item, run_route)
        shortcut_path = app_shortcut_path(run_route)
        run_state = "normal" if run_allowed_during_activity(self.busy, self._busy_kind) else "disabled"
        if len(run_routes) > 1:
            run_menu = self.tk.Menu(menu, tearoff=False)
            labels = [
                route.target.name if isinstance(route.target, Path) else str(route.target).split("!", 1)[-1]
                for route in run_routes
            ]
            for route, label in zip(run_routes, labels):
                if labels.count(label) > 1 and isinstance(route.target, Path):
                    label = f"{label} — {route.target.parent}"
                run_menu.add_command(
                    label=label,
                    command=lambda chosen=route: self._launch_item(item, chosen),
                )
            menu.add_cascade(label="Run", menu=run_menu, state=run_state)
        elif run_route is not None:
            menu.add_command(
                label="Run",
                accelerator="Ctrl+Enter",
                command=lambda selected_item=item: self._launch_item(selected_item),
                state=run_state,
            )
        if containing_target is not None:
            menu.add_command(
                label="Open containing folder",
                command=lambda selected_item=item: self._open_item_containing_folder(
                    selected_item
                ),
            )
        if shortcut_path is not None:
            menu.add_command(
                label="Open shortcut folder",
                command=lambda selected_item=item: self._open_item_shortcut_folder(
                    selected_item
                ),
            )
        if run_routes or containing_target is not None or shortcut_path is not None:
            menu.add_separator()
        if not self._last_scan_all_packages:
            menu.add_command(
                label="Update this package…",
                command=lambda selected_item=item: self._update_single_item(selected_item),
                state=(
                    "normal"
                    if not self.busy and self._context_item_can_update(item)
                    else "disabled"
                ),
            )
            menu.add_separator()
        menu.add_command(
            label="Package details...",
            command=lambda selected_item=item: self.show_item_details(selected_item),
        )
        menu.add_command(
            label="Copy package details",
            command=lambda selected_item=item: self._copy_text(
                self.item_details_text(selected_item),
                log_message=f"Copied details for {selected_item.name}",
            ),
        )
        portable_update_page = portable_manual_update_page(item)
        if portable_update_page:
            menu.add_command(
                label="Copy manual update page URL",
                command=lambda url=portable_update_page, selected_item=item: self._copy_text(
                    url,
                    log_message=f"Copied manual update page for {selected_item.name}",
                ),
            )
        if item.provider == MICROSOFT_STORE_PROVIDER_KEY:
            menu.add_separator()
            exact_store_product = (
                item.source.casefold() == MICROSOFT_STORE_SOURCE
                and MICROSOFT_STORE_PRODUCT_ID_RE.fullmatch(item.package_id) is not None
            )
            menu.add_command(
                label=(
                    "Open in Microsoft Store" if exact_store_product else "Find in Microsoft Store"
                ),
                command=lambda selected_item=item: self._open_microsoft_store_item(selected_item),
            )
            menu.add_command(
                label="Open Microsoft Store updates",
                command=self._open_microsoft_store_updates,
            )
        hold_record = self.settings.data.get("attempt_holds", {}).get(item.candidate_key)
        if winget_permission_repair_target(item, hold_record) is not None:
            menu.add_command(
                label="Create WinGet permission repair script…",
                command=lambda selected_item=item: self._create_winget_repair_script(selected_item),
                state=(
                    "disabled"
                    if self.busy or self._item_inventory_is_provisional(item)
                    else "normal"
                ),
            )
        uninstall_route = self._uninstall_route(item)
        if all_selected_portables or uninstall_route is not None:
            menu.add_separator()
        if all_selected_portables:
            menu.add_command(
                label="Clear selected portables from list",
                command=lambda selected_keys=context_rows: (
                    self._clear_selected_portables_from_list(selected_keys)
                ),
                state=(
                    "disabled"
                    if self.busy or self._portable_scan_active
                    else "normal"
                ),
            )
        if uninstall_route is not None:
            provider, _command = uninstall_route
            menu.add_command(
                label=(
                    "Uninstall portable app…"
                    if item.provider == PORTABLE_PROVIDER_KEY
                    else f"Uninstall through {provider.label}…"
                ),
                command=lambda selected_item=item: self._request_item_uninstall(selected_item),
                state="disabled" if self.busy else "normal",
            )
        menu.add_separator()
        toggle_label = (
            "Uncheck selected package(s)" if item.selected else "Check selected package(s)"
        )
        menu.add_command(
            label=toggle_label,
            command=lambda selected_row=row: self._toggle_tree_rows_like(selected_row),
            state="disabled" if self.busy else "normal",
        )
        if not self._last_scan_all_packages:
            menu.add_separator()
            menu.add_command(
                label="Ignore this update",
                command=lambda selected_item=item: self._ignore_item(selected_item),
                state="disabled" if self.busy else "normal",
            )
        menu.tk_popup(event.x_root, event.y_root)
        menu.grab_release()
        return "break"

    def _open_microsoft_store_uri(self, uri: str, *, summary: str) -> None:
        try:
            os.startfile(uri)  # type: ignore[attr-defined]
        except OSError as exc:
            self.logger.event(
                "microsoft_store_open_failed",
                uri=uri,
                error=f"{type(exc).__name__}: {exc}",
            )
            self._notify_user(
                f"Microsoft Store could not be opened: {type(exc).__name__}: {exc}",
                level="error",
                summary="Microsoft Store could not be opened; details were logged",
            )
            return
        self.summary_var.set(summary)
        self.logger.event("microsoft_store_opened", uri=uri, summary=summary)

    def _open_microsoft_store_item(self, item: UpdateItem) -> None:
        if (
            item.provider != MICROSOFT_STORE_PROVIDER_KEY
            or item.source.casefold() != MICROSOFT_STORE_SOURCE
            or MICROSOFT_STORE_PRODUCT_ID_RE.fullmatch(item.package_id) is None
        ):
            uri = "ms-windows-store://search/?query=" + urllib.parse.quote(item.name)
            summary = f"Opened Microsoft Store search for {item.name}"
        else:
            uri = "ms-windows-store://pdp/?ProductId=" + urllib.parse.quote(item.package_id)
            summary = f"Opened {item.name} in Microsoft Store"
        self._open_microsoft_store_uri(uri, summary=summary)

    def _open_microsoft_store_updates(self) -> None:
        self._open_microsoft_store_uri(
            MICROSOFT_STORE_UPDATES_URI,
            summary="Opened Microsoft Store updates",
        )

    def _create_winget_repair_script(self, item: UpdateItem) -> None:
        """Materialize a reviewable admin script without running or elevating it."""
        if self.busy:
            return
        hold_record = self.settings.data.get("attempt_holds", {}).get(item.candidate_key)
        try:
            script_path = write_winget_permission_repair_script(item, hold_record)
        except (OSError, ValueError) as exc:
            self.logger.event(
                "winget_permission_repair_script_failed",
                item=item_diagnostic_fields(item),
                error=str(exc),
            )
            self._notify_user(
                f"Could not create the narrow WinGet repair script: {exc}",
                level="warning",
                summary="WinGet repair script could not be created",
            )
            return
        self.logger.event(
            "winget_permission_repair_script_created",
            item=item_diagnostic_fields(item),
            script_path=str(script_path),
            executed=False,
        )
        self._append_log(
            "WinGet permission repair script created for "
            f"{item.name}: {script_path}. It was not executed."
        )
        self._notify_user(
            "Repair script created. Review it, run it as administrator, then release "
            "this package hold and retry.",
            summary="WinGet repair script is ready for review",
        )
        with contextlib.suppress(OSError):
            os.startfile(script_path.parent)  # type: ignore[attr-defined]

    def _run_from_keyboard(self, event: Any) -> str:
        visible_rows = self.tree.get_children("")
        if event.widget is self.search_entry:
            item = self.items.get(visible_rows[0]) if len(visible_rows) == 1 else None
        else:
            item = self.focused_or_selected_item()
            if self.tree.focus() not in visible_rows:
                item = None
        if item is None:
            self._notify_user("Select one app, or narrow the search to one result, then press Ctrl+Enter.")
        else:
            self._launch_item(item)
        return "break"

    def _launch_item(self, item: UpdateItem, chosen: AppRunRoute | None = None) -> None:
        """Activate a revalidated local route without elevation."""

        if not run_allowed_during_activity(self.busy, self._busy_kind):
            return
        routes = app_run_routes(item)
        route = chosen if chosen in routes else (routes[0] if chosen is None and len(routes) == 1 else None)
        if route is None:
            self._notify_user(
                (f"{item.name} has several launch choices; choose Run from its right-click menu."
                 if len(routes) > 1 else f"{item.name} no longer has a verified local run route."),
                level="warning",
                summary="Choose an available launch route from the app's right-click menu",
            )
            return
        try:
            activate_app_route(route)
        except OSError as exc:
            self._notify_user(
                f"{item.name} could not be run: {type(exc).__name__}: {exc}",
                level="error",
                summary=f"Could not run {item.name}; details were logged",
            )
            self.logger.event(
                "package_launch_failed",
                item=item_diagnostic_fields(item),
                route_kind=route.kind,
                route_target=str(route.target),
                error=f"{type(exc).__name__}: {exc}",
            )
            return
        if not self.busy:
            self.summary_var.set(f"Started {item.name}")
        self._append_log(f"Started {item.name} through its {route.kind}: {route.target}")
        self.logger.event(
            "package_launched",
            item=item_diagnostic_fields(item),
            route_kind=route.kind,
            route_target=str(route.target),
        )

    def _open_item_containing_folder(self, item: UpdateItem) -> None:
        """Reveal the terminal executable/script while preserving shortcut launch behavior."""

        route = app_run_route(item)
        target = app_containing_target(item, route)
        if target is None:
            self._notify_user(
                f"{item.name} no longer has an unambiguous local folder.",
                level="warning",
                summary="Containing folder could not be opened; rescan may refresh it",
            )
            return
        try:
            reveal_in_windows_explorer(target)
        except OSError as exc:
            self._notify_user(
                f"The folder for {item.name} could not be opened: "
                f"{type(exc).__name__}: {exc}",
                level="error",
                summary=f"Could not open the folder for {item.name}; details were logged",
            )
            self.logger.event(
                "package_containing_folder_open_failed",
                item=item_diagnostic_fields(item),
                route_kind=route.kind if route is not None else "installed-location",
                route_target=str(route.target) if route is not None else "",
                navigation_target=str(target),
                error=f"{type(exc).__name__}: {exc}",
            )
            return
        self.summary_var.set(f"Opened the folder containing {item.name}")
        self.logger.event(
            "package_containing_folder_opened",
            item=item_diagnostic_fields(item),
            route_kind=route.kind if route is not None else "installed-location",
            route_target=str(route.target) if route is not None else "",
            navigation_target=str(target),
        )

    def _open_item_shortcut_folder(self, item: UpdateItem) -> None:
        """Reveal the original saved route without resolving or launching it."""

        route = app_run_route(item)
        shortcut = app_shortcut_path(route)
        if shortcut is None:
            self._notify_user(
                f"{item.name} no longer has an unambiguous saved shortcut.",
                level="warning",
                summary="Shortcut folder could not be opened; rescan may refresh it",
            )
            return
        try:
            reveal_in_windows_explorer(shortcut)
        except OSError as exc:
            self._notify_user(
                f"The shortcut folder for {item.name} could not be opened: "
                f"{type(exc).__name__}: {exc}",
                level="error",
                summary=f"Could not open the shortcut folder for {item.name}; details were logged",
            )
            self.logger.event(
                "package_shortcut_folder_open_failed",
                item=item_diagnostic_fields(item),
                shortcut=str(shortcut),
                error=f"{type(exc).__name__}: {exc}",
            )
            return
        self.summary_var.set(f"Opened the shortcut folder for {item.name}")
        self.logger.event(
            "package_shortcut_folder_opened",
            item=item_diagnostic_fields(item),
            shortcut=str(shortcut),
        )

    def _context_item_can_update(self, item: UpdateItem) -> bool:
        if self._last_scan_all_packages or item.key not in self._scan_view_items[False]:
            return False
        return self._item_is_bulk_selectable(item) or bool(
            self._selected_winget_rows_needing_preflight((item,))
        )

    def _update_single_item(self, item: UpdateItem) -> None:
        if self.busy or self._last_scan_all_packages:
            return
        current = self._scan_view_items[False].get(item.key)
        if current is None or not self._context_item_can_update(current):
            self._notify_user(
                f"{item.name} is no longer a normal update candidate. Review its current status.",
                level="warning",
                summary="Package is not safely updateable here",
            )
            return
        needs_check = self._selected_winget_rows_needing_preflight((current,))
        if needs_check:
            self._start_selected_winget_preflight([current.key], needs_check)
            return
        self._continue_update_selected([current])

    def _uninstall_route(self, item: UpdateItem) -> tuple[Provider, list[str]] | None:
        if self._item_inventory_is_provisional(item):
            return None
        provider = self.providers.get(item.provider)
        if provider is None or not provider.available():
            return None
        if item.provider == PORTABLE_PROVIDER_KEY:
            plan = refresh_portable_removal_fields(item)
            if plan is None:
                return None
            return (
                provider,
                [APP_NAME, f"delete-portable-{plan.kind}", plan.target],
            )
        if item.requires_admin and (item.scope != "machine" or not provider.elevation_allowed):
            return None
        try:
            command = provider.build_uninstall_command(item)
        except (OSError, ValueError):
            return None
        return (provider, command) if command else None

    def _request_item_uninstall(self, item: UpdateItem) -> None:
        if self.busy:
            return
        route = self._uninstall_route(item)
        if route is None:
            self._notify_user(
                f"{item.name} no longer has a safe, exact uninstall route. Rescan and review Details.",
                level="warning",
                summary="Exact uninstall route unavailable",
            )
            return
        provider, command = route
        if (
            item.requires_admin
            and not self.process_is_admin
            and not self.settings.data.get("auto_elevate", True)
        ):
            self._notify_user(
                "This machine-scope uninstall needs administrator rights. Enable the one-prompt "
                "elevation option in Providers before retrying.",
                level="warning",
                summary="Machine uninstall needs elevation enabled",
            )
            return
        run_as = self._run_as_label(item)
        if item.provider == PORTABLE_PROVIDER_KEY:
            target_label = (
                "Entire app folder"
                if item.portable_removal_kind == "folder"
                else "Exact executable only"
            )
            message = (
                "Uninstall this portable app by deleting its proven local target?\n\n"
                f"Name: {item.name}\n"
                f"Installed version: {item.current}\n"
                f"Removal: {target_label}\n"
                f"Target: {item.portable_removal_target}\n"
                f"Run as: {run_as}\n\n"
                f"Why this is offered:\n{item.portable_removal_reason}\n\n"
                "No uninstaller or package-manager command will run. WinDevPilot will "
                "revalidate the target immediately before deletion and refuse the action "
                "if the folder contents or path have become ambiguous."
            )
        else:
            message = (
                f"Uninstall this exact package through {provider.label}?\n\n"
                f"Name: {item.name}\n"
                f"Package ID: {item.package_id}\n"
                f"Installed version: {item.current}\n"
                f"Scope: {item.scope}\n"
                f"Run as: {run_as}\n\n"
                f"Command:\n{subprocess.list2cmdline(command)}\n\n"
                "Only this package is requested. The package manager may refuse removal when "
                "other installed packages depend on it. WinDevPilot will rescan afterward."
            )
        if not self.messagebox.askokcancel("Confirm uninstall", message):
            return
        self.active_update_id = uuid.uuid4().hex
        self.active_attempt_kind = "uninstall"
        _RECENT_WINGET_INVENTORY.invalidate()
        self.cancel_requested.clear()
        self._mark_scan_refresh_needed(
            "An uninstall may have changed installed packages; run a full scan to refresh"
        )
        self._active_operation_original_statuses = {item.key: item.status}
        self._active_operation_results = []
        self._set_busy(True, f"Uninstalling {item.name}", kind="uninstall")
        self.progress.configure(mode="determinate")
        self._set_progress_value(0, animate=False)
        self.summary_var.set(f"Uninstalling {item.name}…")
        self._append_log(
            (
                f"Portable removal requested: {item.name} · "
                f"delete {item.portable_removal_kind} {item.portable_removal_target}"
                if item.provider == PORTABLE_PROVIDER_KEY
                else f"Uninstall requested: {item.name} through {provider.label}"
            )
        )
        self.logger.event(
            "uninstall_confirmed",
            operation_id=self.active_update_id,
            item=item_diagnostic_fields(item),
            execution_context="administrator" if item.requires_admin else "current-user",
            requested_command=(
                []
                if item.provider == PORTABLE_PROVIDER_KEY
                else redact_command_parts(command)
            ),
            portable_removal=(
                {
                    "kind": item.portable_removal_kind,
                    "target": item.portable_removal_target,
                    "reason": item.portable_removal_reason,
                }
                if item.provider == PORTABLE_PROVIDER_KEY
                else {}
            ),
        )
        item_snapshot = dataclasses.replace(item)
        source_all_packages = self._last_scan_all_packages
        self._start_guarded_worker(
            lambda: self._uninstall_worker(item_snapshot, source_all_packages),
            name="wdp-uninstall",
            operation="uninstall",
        )

    def _uninstall_worker(self, item: UpdateItem, source_all_packages: bool) -> None:
        provider = self.providers[item.provider]
        self.events.put(("item_status", (item.key, "Uninstalling…", 1, 1)))
        self.events.put(
            (
                "log",
                (
                    f"Removing portable app {item.name}…"
                    if item.provider == PORTABLE_PROVIDER_KEY
                    else f"Uninstalling {item.name} through {provider.label}…"
                ),
            )
        )
        if item.provider == PORTABLE_PROVIDER_KEY:
            result = remove_portable_item(item)
            entry = command_result_entry(
                item,
                provider,
                result,
                execution_context="current-user-internal-removal",
                operation="uninstall",
            )
            if entry.get("success"):
                try:
                    entry["internal_removal_verified"] = not Path(item.portable_removal_target).exists()
                    if entry["internal_removal_verified"]:
                        self.portable_inventory.forget_executable(item.portable_executable)
                except OSError as exc:
                    self.events.put(("log", f"Portable removal verification/cache warning: {exc}"))
            self.logger.event(
                "uninstall_result",
                operation_id=self.active_update_id,
                item=item_diagnostic_fields(item),
                result=entry,
            )
            self.events.put(("uninstall_done", (item.key, entry, source_all_packages)))
            return
        version_result = run_capture(provider.version_command(), timeout=60)
        self.logger.event(
            "uninstall_provider_runtime",
            operation_id=self.active_update_id,
            provider={
                "key": provider.key,
                "label": provider.label,
                "executable": provider.executable,
                "resolved_executable": shutil.which(provider.executable),
            },
            version_probe=command_diagnostic_fields(version_result),
        )
        try:
            if item.requires_admin:
                if self.process_is_admin:
                    revalidation_failure = revalidate_elevated_winget_machine_target(item)
                    if revalidation_failure is not None:
                        entry = revalidation_failure
                    else:
                        entry = execute_items_direct(
                            [item],
                            self.providers,
                            execution_context="already-elevated-process",
                            operation="uninstall",
                        )[0]
                else:
                    entry = execute_elevated_batch([item], operation="uninstall")[0]
            else:
                result = provider.uninstall(item)
                entry = command_result_entry(
                    item,
                    provider,
                    result,
                    execution_context="current-user",
                    operation="uninstall",
                )
        except ElevationCancelled as exc:
            entry = diagnostic_failure_entry(
                item,
                str(exc),
                execution_context="uac-launch",
                returncode=ERROR_CANCELLED,
                cancelled=True,
            )
        except Exception as exc:
            entry = diagnostic_failure_entry(
                item,
                f"Uninstall launch failed: {type(exc).__name__}: {exc}",
                execution_context="uninstall-launch",
            )
        self.logger.event(
            "uninstall_result",
            operation_id=self.active_update_id,
            item=item_diagnostic_fields(item),
            result=entry,
        )
        self.events.put(("uninstall_done", (item.key, entry, source_all_packages)))

    def _finish_uninstall(
        self, item_key: str, entry: dict[str, Any], rescan_all_packages: bool
    ) -> None:
        self._active_operation_original_statuses.clear()
        self._active_operation_results.clear()
        item = self._scan_view_item(
            item_key,
            prefer_all_packages=rescan_all_packages,
        )
        success = bool(entry.get("success"))
        cancelled = bool(entry.get("cancelled"))
        if item is not None:
            status = (
                ("Restart required to finish removal" if entry.get("needs_reboot")
                 else "Removal reported; verification pending")
                if success else "Cancelled" if cancelled else "Uninstall failed"
            )
            self._set_scan_view_item_status(item_key, status)
        output = str(entry.get("output", "")).strip()
        error = str(entry.get("error", "")).strip()
        if output:
            self._append_log(f"Uninstall command output:\n{output}", already_redacted=True)
        if error:
            self._append_log(f"Uninstall error: {error}", already_redacted=True)
        name = item.name if item is not None else item_key
        if success:
            if item is not None:
                pending = getattr(self, "_pending_uninstall_verifications", {})
                self._pending_uninstall_verifications = pending
                pending[item_key] = (dataclasses.replace(item), dict(entry))
            invalidate_start_menu_shortcut_index()
            self._notify_user(
                (f"{name}: removal reported; restart required. Installation history is retained."
                 if entry.get("needs_reboot") else
                 f"{name}: removal reported. Checking fresh installed inventory before confirming."),
                level="info",
                summary=f"Verifying removal: {name}",
            )
        elif cancelled:
            self._notify_user(
                f"Uninstall cancelled for {name}.",
                level="warning",
                summary="Uninstall cancelled",
            )
        else:
            self._notify_user(
                f"{name} was not uninstalled. Review the detailed command output below.",
                level="error",
                summary=f"Uninstall failed: {name}",
            )
        self._set_progress_value(100)
        self._set_busy(False)
        self._schedule_post_update_scan()
        self._verify_pending_uninstalls((), set())

    def _verify_pending_uninstalls(
        self, packages: Sequence[UpdateItem], fresh_providers: set[str],
    ) -> None:
        pending = getattr(self, "_pending_uninstall_verifications", {})
        for key, (item, receipt) in tuple(pending.items()):
            internal_verified = (item.provider == PORTABLE_PROVIDER_KEY
                                 and receipt.get("success")
                                 and receipt.get("internal_removal_verified") is True)
            if (item.provider not in fresh_providers and not internal_verified) or receipt.get("needs_reboot"):
                continue
            # Any same package in the selected scope prevents an absence claim;
            # registration ordering and changed source labels cannot imply removal.
            retained = not internal_verified and any(
                other.provider == item.provider
                and other.package_id.casefold() == item.package_id.casefold()
                and other.scope.casefold() == item.scope.casefold()
                for other in packages
            )
            if retained:
                self._set_scan_view_item_status(key, "Removal unconfirmed; registration still present")
                continue
            original_history = dict(self.settings.data.get("package_history", {}))
            if forget_package_history_for_item(self.settings.data, item):
                try:
                    self.settings.save()
                except OSError:
                    self.settings.data["package_history"] = original_history
                    continue
            pending.pop(key, None)
            self.logger.event("uninstall_verified", item=item_diagnostic_fields(item))
            evidence = "the confirmed filesystem target" if internal_verified else "fresh installed inventory"
            self._notify_user(f"Removal verified: {item.name} is absent from {evidence}.",
                              level="success", summary=f"Removed {item.name}")

    def _suggested_install_route(
        self, suggestion: PackageSuggestion
    ) -> tuple[Provider, list[str]] | None:
        provider = self.providers.get(suggestion.provider_key)
        if provider is None or not provider.available():
            return None
        try:
            command = suggestion_install_command_parts(suggestion)
        except ValueError:
            return None
        return (provider, command)

    def _request_suggested_install(
        self,
        suggestion: PackageSuggestion,
        finished_callback: Callable[[bool], None] | None = None,
    ) -> None:
        if self.busy:
            self._notify_user(
                "Finish the current package operation or scan before starting an install.",
                summary="Suggested install is waiting for the current operation",
            )
            return
        route = self._suggested_install_route(suggestion)
        if route is None:
            self._notify_user(
                f"The package manager for {suggestion.title} is not available on this system.",
                level="warning",
                summary="Suggested install provider is unavailable",
            )
            return
        provider, command = route
        self.active_update_id = uuid.uuid4().hex
        self.active_attempt_kind = "install"
        self.cancel_requested.clear()
        _RECENT_WINGET_INVENTORY.invalidate()
        self._mark_scan_refresh_needed(
            "An install may have changed installed packages; run a full scan to refresh"
        )
        self._active_operation_original_statuses = {}
        self._active_operation_results = []
        self._set_busy(True, f"Installing {suggestion.title}", kind="install")
        self.progress.configure(mode="determinate")
        self._set_progress_value(5, animate=False)
        self.summary_var.set(f"Installing {suggestion.title} through {provider.label}…")
        self._append_log(f"Installing suggested package: {suggestion.title} through {provider.label}")
        self.logger.event(
            "suggested_install_started",
            operation_id=self.active_update_id,
            suggestion=suggestion.to_dict(),
            provider={
                "key": provider.key,
                "label": provider.label,
                "executable": provider.executable,
                "resolved_executable": shutil.which(provider.executable),
            },
            requested_command=redact_command_parts(command),
        )
        self._start_guarded_worker(
            lambda: self._suggested_install_worker(
                suggestion,
                command,
                finished_callback,
            ),
            name="wdp-suggested-install",
            operation="suggested-install",
        )

    def _suggested_install_worker(
        self,
        suggestion: PackageSuggestion,
        command: list[str],
        finished_callback: Callable[[bool], None] | None,
    ) -> None:
        provider = self.providers[suggestion.provider_key]
        version_result = run_capture(provider.version_command(), timeout=60)
        result = run_capture(command, timeout=7200)
        related_installer_logs = (
            collect_winget_installer_logs(result)
            if provider.key == WingetProvider.key
            else []
        )
        success = provider.succeeded(result)
        status_hint = provider.status_hint(result)
        if not success:
            status_hint = (
                winget_installer_failure_hint(result, related_installer_logs) or status_hint
            )
        self.logger.event(
            "suggested_install_finished",
            operation_id=self.active_update_id,
            suggestion=suggestion.to_dict(),
            provider_runtime=command_diagnostic_fields(version_result),
            success=success,
            needs_reboot=provider.needs_reboot(result),
            warnings=provider.result_warnings(result),
            status_hint=status_hint,
            result=command_diagnostic_fields(result),
            related_installer_logs=related_installer_logs,
        )
        self.events.put(
            (
                "suggested_install_done",
                (suggestion, result, status_hint, finished_callback),
            )
        )

    def _remember_confirmed_history_absences(
        self,
        installed_items: Sequence[UpdateItem],
        fresh_provider_keys: set[str],
        observed_at: str | Mapping[str, str],
    ) -> None:
        """Called only after a complete scan, excluding reused provider snapshots."""

        previous = self.settings.data.get("package_history", {})
        updated = previous
        for key in sorted(fresh_provider_keys):
            boundary = observed_at.get(key, "") if isinstance(observed_at, Mapping) else observed_at
            if boundary:
                updated = remember_package_history_absences(
                    updated, installed_items, {key}, boundary
                )
        if updated == previous:
            return
        self.settings.data["package_history"] = updated
        try:
            self.settings.save()
        except OSError as exc:
            self.settings.data["package_history"] = previous
            self._append_log(f"Could not remember inventory absences: {exc}", show_in_ui=False)
            return
        self.logger.event(
            "package_history_absences_recorded",
            changed_count=sum(updated[key] != previous[key] for key in updated),
            fresh_provider_keys=sorted(fresh_provider_keys),
        )

    def _confirm_pending_suggested_install_history(
        self,
        installed_items: Sequence[UpdateItem],
    ) -> None:
        """Notarize suggested installs only after a current inventory proves presence."""

        if not self._pending_suggested_install_history:
            return
        original_history = dict(self.settings.data.get("package_history", {}))
        history = dict(original_history)
        confirmed: list[str] = []
        confirmed_pending: dict[str, dict[str, Any]] = {}
        discarded: list[str] = []
        for pending_key, pending in tuple(self._pending_suggested_install_history.items()):
            provider_key = str(pending.get("provider", ""))
            package_id = str(pending.get("package_id", ""))
            if provider_key not in self._scan_current_provider_keys:
                continue
            matches = [
                item
                for item in installed_items
                if item.provider == provider_key
                and item.package_id.casefold() == package_id.casefold()
            ]
            self._pending_suggested_install_history.pop(pending_key, None)
            if len(matches) != 1:
                discarded.append(package_id)
                self._append_log(
                    (
                        f"Suggested install history was not recorded for {package_id}: "
                        "the refreshed inventory did not contain one unambiguous instance"
                    ),
                    show_in_ui=False,
                )
                continue
            installed = matches[0]
            confirmed_pending[pending_key] = dict(pending)
            history = remember_package_history_event(
                history,
                provider=installed.provider,
                package_id=installed.package_id,
                name=installed.name or str(pending.get("name", "")),
                action="install",
                observed_at=str(pending.get("observed_at", "")) or utc_now_iso(),
                version=installed.current,
                scope=installed.scope,
                source=installed.source,
            )
            confirmed.append(package_id)
        if history == original_history:
            return
        self.settings.data["package_history"] = history
        try:
            self.settings.save()
        except OSError as exc:
            self.settings.data["package_history"] = original_history
            self._pending_suggested_install_history.update(confirmed_pending)
            self._append_log(
                f"Could not remember inventory-confirmed WinDevPilot installs: {exc}",
                show_in_ui=False,
            )
            return
        self.logger.event(
            "package_history_updated",
            update_id=self.active_update_id,
            remembered_count=len(history),
            source="inventory-confirmed-suggested-install",
            confirmed_package_ids=confirmed,
            discarded_package_ids=discarded,
        )

    def _finish_suggested_install(
        self,
        suggestion: PackageSuggestion,
        result: CommandResult,
        status_hint: str,
        finished_callback: Callable[[bool], None] | None,
    ) -> None:
        self._active_operation_original_statuses.clear()
        self._active_operation_results.clear()
        provider = self.providers[suggestion.provider_key]
        success = provider.succeeded(result)
        outcome = provider.outcome(result)
        output = result.output.strip()
        if output:
            self._append_log(
                f"Suggested install command output for {suggestion.title}:\n{output}",
                show_in_ui=False,
            )
        if result.exception:
            self._append_log(
                f"Suggested install launch error for {suggestion.title}: {result.exception}",
                show_in_ui=False,
            )
        self._set_progress_value(100)
        self._set_busy(False)
        if success:
            if outcome in {"updated", "updated-restart-required"}:
                pending_key = (
                    f"{suggestion.provider_key}\0{suggestion.winget_id}"
                ).casefold()
                self._pending_suggested_install_history[pending_key] = {
                    "provider": suggestion.provider_key,
                    "package_id": suggestion.winget_id,
                    "name": suggestion.title,
                    "observed_at": result.finished_at or utc_now_iso(),
                }
            invalidate_start_menu_shortcut_index()
            path_report = refresh_process_path_from_windows_environment()
            self._path_refresh_report = merge_windows_path_refresh_reports(
                self._path_refresh_report,
                path_report,
            )
            restart = " A Windows restart is required." if provider.needs_reboot(result) else ""
            message = (
                f"{suggestion.title} is already installed and current through {provider.label}."
                if outcome == "already-current"
                else (
                    f"{provider.label} reported a successful install of {suggestion.title}; "
                    f"WinDevPilot will confirm it in refreshed inventory.{restart}"
                )
            )
            self._notify_user(
                message,
                level="success",
                summary=(
                    f"Already installed: {suggestion.title}"
                    if outcome == "already-current"
                    else f"Install reported successful: {suggestion.title}"
                ),
            )
            self.logger.event(
                "post_install_toolchain_refresh_requested",
                suggestion_id=suggestion.winget_id,
                process_path_refreshed=path_report.changed,
                path_recovery=dataclasses.asdict(path_report),
                health_window_open=bool(self._toolchain_health_window),
            )
            self._refresh_open_toolchain_health()
        else:
            detail = status_hint or f"{provider.label} exited {exit_code_hex(result.returncode)}"
            self._notify_user(
                f"{suggestion.title} was not installed. {detail} Full command evidence is in the session log.",
                level="error",
                summary=f"Install failed: {suggestion.title}",
            )
        if finished_callback is not None:
            with contextlib.suppress(Exception):
                finished_callback(success)
        self._schedule_post_update_scan()

    def _toggle_tree_rows_like(self, row: str) -> None:
        clicked = self.items.get(row)
        if clicked is None:
            return
        target_state = not clicked.selected
        selected_rows = [str(value) for value in self.tree.selection() if str(value) in self.items]
        rows = selected_rows if row in selected_rows and len(selected_rows) > 1 else [row]
        blocked_items: list[UpdateItem] = []
        changed = 0
        for selected_row in rows:
            item = self.items[selected_row]
            if not self._item_is_actionable(item):
                blocked_items.append(item)
                continue
            if item.selected != target_state:
                item.selected = target_state
                self._selection_touched_keys.add(item.key)
                changed += 1
        if blocked_items:
            self._report_blocked_selection(blocked_items, changed=changed)
        if self._sort_state and self._sort_state[0] == "selected":
            self._schedule_rebuild_tree()
        else:
            for selected_row in rows:
                self._refresh_item_row(self.items[selected_row])
        self._refresh_scan_summary_counts()

    def _report_blocked_selection(
        self,
        blocked_items: Sequence[UpdateItem],
        *,
        changed: int,
    ) -> None:
        """Explain blocked checkboxes once per scan/reason instead of flooding the log."""

        inventory_only = any(
            item.classification == CLASS_INVENTORY_ONLY for item in blocked_items
        )
        unresolved_scope = any(
            item.provider == WingetProvider.key
            and item.classification != CLASS_INVENTORY_ONLY
            and item.scope not in {"user", "machine"}
            for item in blocked_items
        )
        pinned = any(
            item.provider == WingetProvider.key
            and item.status == "Pinned — left unchanged"
            for item in blocked_items
        )
        messages: list[str] = []
        reason_parts: list[str] = []
        if inventory_only:
            messages.append(
                "All packages does not select update candidates; switch to Updates to choose "
                "packages to update"
            )
            reason_parts.append("inventory")
        if unresolved_scope:
            total = sum(
                item.provider == WingetProvider.key
                and item.classification != CLASS_INVENTORY_ONLY
                and item.scope not in {"user", "machine"}
                for item in self.items.values()
            )
            messages.append(
                f"{total} WinGet update(s) cannot be selected because their user-or-machine "
                "installation scope could not be proven"
            )
            reason_parts.append("scope")
        if pinned:
            messages.append("WinGet-pinned packages remain unchanged")
            reason_parts.append("pin")
        if not messages:
            messages.append(f"{len(blocked_items)} package(s) cannot be selected safely")
            reason_parts.append("other")
        if changed:
            messages.append(f"{changed} other package(s) were changed as requested")
        message = "; ".join(messages) + "."
        summary = "Some packages were left unselected"
        notice_key = (self._active_scan_generation, "+".join(reason_parts))
        if notice_key not in self._selection_block_notices:
            self._selection_block_notices.add(notice_key)
            self._notify_user(message, level="warning", summary=summary)
        else:
            # Repeat checkbox attempts still get immediate in-window feedback,
            # but the persistent session log receives one aggregated explanation.
            self.summary_var.set(summary)

    def _tree_mousewheel(self, event: Any) -> str | None:
        # Leave Shift/horizontal and accelerated/modifier bindings to Tk. Its
        # distinct TouchpadScroll event never enters this handler.
        if event.state & (0x0001 | 0x0004 | 0x0008 | 0x20000):
            self._tree_wheel_remainder = 0
            return None
        if not event.delta % 120 and not self._tree_wheel_remainder:
            return None  # Preserve the exact ordinary-notch class behavior.
        steps, self._tree_wheel_remainder = accumulated_wheel_rows(
            event.delta, self._tree_wheel_remainder, self._tree_wheel_rows_per_notch
        )
        if steps:
            self.tree.yview_scroll(steps, "units")
        return "break"

    def _tree_motion(self, event: Any) -> None:
        if time.monotonic() < self._icon_scroll_quiet_until:
            self._tree_hover_needs_refresh = True
            return
        region = self.tree.identify_region(event.x, event.y)
        column = self.tree.identify_column(event.x)
        column_name = self._tree_display_column_name(column)
        row = self.tree.identify_row(event.y)
        hover_row = row if region in {"cell", "tree"} and row in self.items else ""
        if hover_row != self._hover_row:
            previous_row = self._hover_row
            self._hover_row = hover_row
            for changed_row in (previous_row, hover_row):
                item = self.items.get(changed_row)
                if item is not None and self.tree.exists(changed_row):
                    getattr(self, "_tree_row_presentations", {}).pop(changed_row, None)
                    self.tree.item(changed_row, tags=self._row_tags(item))
        if region == "heading" and column == "#0":
            self._schedule_tooltip(
                "header:art-sort",
                "Sort by icon color\n"
                "▲ One combined color order for all icons.\n"
                "△△ Generated icons first, then app icons; each group sorted by color.\n"
                "Click again to switch between these two modes.",
                self.tree.winfo_rootx() + event.x + self.visuals.px(18),
                self.tree.winfo_rooty() + event.y + self.visuals.px(18),
                event.x_root,
                event.y_root,
            )
            return
        if (
            region != "cell"
            or column_name not in {"status", "installed_date"}
            or row not in self.items
        ):
            self._hide_tooltip()
            return
        item = self.items[row]
        if column_name == "installed_date":
            date = self._installed_service_date_evidence(item)
            tooltip_key = (
                f"date:{row}:{date.date}:{date.source}:{date.is_estimate}"
            )
            if tooltip_key == self._tooltip_key and self._tooltip_window is not None:
                return
            if date.date:
                certainty = (
                    "Approximate evidence, not a proven original installation date."
                    if date.is_estimate
                    else "Recorded install or service date; not necessarily the first installation."
                )
                tooltip = "\n".join(
                    (
                        f"{item.name}",
                        f"Installed / last serviced: {date.detail_text}",
                        certainty,
                        f"Evidence: {date.source or 'source not recorded'}",
                    )
                )
            else:
                tooltip = (
                    f"{item.name}\nNo trustworthy install or service date was found. "
                    "WinDevPilot leaves uncertain dates blank."
                )
            self._schedule_tooltip(
                tooltip_key,
                tooltip,
                self.tree.winfo_rootx() + event.x + self.visuals.px(18),
                self.tree.winfo_rooty() + event.y + self.visuals.px(18),
                event.x_root,
                event.y_root,
            )
            return
        tooltip_key = f"{row}:{item.status}:{item.classification}:{item.applicability_prediction}"
        if tooltip_key == self._tooltip_key and self._tooltip_window is not None:
            return
        self._schedule_tooltip(
            tooltip_key,
            self.status_tooltip_text(item),
            self.tree.winfo_rootx() + event.x + self.visuals.px(18),
            self.tree.winfo_rooty() + event.y + self.visuals.px(18),
            event.x_root,
            event.y_root,
        )

    def _refresh_tree_hover_after_scroll(self) -> None:
        """Re-evaluate the row under a stationary pointer once scrolling settles."""
        if not self._tree_hover_needs_refresh:
            return
        self._tree_hover_needs_refresh = False
        x_root, y_root = self.tree.winfo_pointerxy()
        if self.tree.winfo_containing(x_root, y_root) is not self.tree:
            return
        event = self.tk.Event()
        event.x_root, event.y_root = x_root, y_root
        event.x = x_root - self.tree.winfo_rootx()
        event.y = y_root - self.tree.winfo_rooty()
        self._tree_motion(event)

    def _tree_leave(self, _event: Any = None) -> None:
        if _event is not None:
            self._tree_wheel_remainder = 0
        previous_row = self._hover_row
        self._hover_row = ""
        item = self.items.get(previous_row)
        if item is not None and self.tree.exists(previous_row):
            getattr(self, "_tree_row_presentations", {}).pop(previous_row, None)
            self.tree.item(previous_row, tags=self._row_tags(item))
        self._hide_tooltip()

    def _bind_widget_tooltip(self, widget: Any, text: str) -> None:
        tooltip_text = text.strip()
        if not tooltip_text:
            return

        def show(event: Any) -> None:
            self._schedule_tooltip(
                f"widget:{id(widget)}",
                tooltip_text,
                widget.winfo_rootx() + event.x + self.visuals.px(16),
                widget.winfo_rooty() + event.y + self.visuals.px(18),
                event.x_root,
                event.y_root,
            )

        def move(event: Any) -> None:
            if self._tooltip_key == f"widget:{id(widget)}":
                return
            show(event)

        widget.bind("<Enter>", show, add="+")
        widget.bind("<Motion>", move, add="+")
        widget.bind("<Leave>", self._hide_tooltip, add="+")
        widget.bind("<ButtonPress>", self._hide_tooltip, add="+")

    def _schedule_tooltip(
        self,
        tooltip_key: str,
        text: str,
        x: int,
        y: int,
        pointer_x: int,
        pointer_y: int,
    ) -> None:
        if not text.strip():
            self._hide_tooltip()
            return
        if tooltip_key == self._tooltip_key and self._tooltip_window is not None:
            return
        pending = self._tooltip_pending
        tolerance = self.visuals.px(TOOLTIP_MOVE_TOLERANCE_PX)
        if (
            pending is not None
            and pending[0] == tooltip_key
            and abs(pointer_x - pending[4]) <= tolerance
            and abs(pointer_y - pending[5]) <= tolerance
        ):
            self._tooltip_pending = (tooltip_key, text, x, y, pending[4], pending[5])
            return
        self._cancel_after_id("_tooltip_after_id")
        self._tooltip_pending = (tooltip_key, text, x, y, pointer_x, pointer_y)
        self._tooltip_after_id = self.root.after(
            TOOLTIP_DELAY_MS,
            self._show_pending_tooltip,
        )

    def _show_pending_tooltip(self) -> None:
        self._tooltip_after_id = None
        pending = self._tooltip_pending
        self._tooltip_pending = None
        if pending is None:
            return
        tooltip_key, text, x, y, _pointer_x, _pointer_y = pending
        self._show_tooltip(tooltip_key, text, x, y)

    def _show_tooltip(self, tooltip_key: str, text: str, x: int, y: int) -> None:
        self._hide_tooltip(cancel_pending=False)
        if not text.strip():
            return
        tk = self.tk
        window = tk.Toplevel(self.root, background=self.palette["tooltip_border"])
        window.withdraw()
        window.wm_overrideredirect(True)
        window.wm_geometry(f"+{x}+{y}")
        card = tk.Frame(
            window,
            background=self.palette["tooltip_surface"],
            borderwidth=0,
            highlightthickness=self.visuals.px(1),
            highlightbackground=self.palette["tooltip_border"],
        )
        card.pack()
        accent = tk.Frame(
            card,
            width=self.visuals.px(3),
            background=self.palette["accent_2"],
            borderwidth=0,
            highlightthickness=0,
        )
        accent.pack(side="left", fill="y")
        label = tk.Label(
            card,
            text=text,
            justify="left",
            anchor="w",
            wraplength=self.visuals.px(560),
            background=self.palette["tooltip_surface"],
            foreground=self.palette["tooltip_text"],
            borderwidth=0,
            relief="flat",
            padx=self.visuals.px(10),
            pady=self.visuals.px(8),
            font=self._ui_font(9),
        )
        label.pack(side="left")
        self._tooltip_window = window
        self._tooltip_key = tooltip_key
        window.deiconify()  # Complete, themed, undecorated; tooltips never take focus.

    def _hide_tooltip(self, _event: Any = None, *, cancel_pending: bool = True) -> None:
        if cancel_pending:
            self._cancel_after_id("_tooltip_after_id")
            self._tooltip_pending = None
        window = self._tooltip_window
        self._tooltip_window = None
        self._tooltip_key = ""
        if window is not None:
            with contextlib.suppress(Exception):
                window.destroy()

    def _toggle_focused(self) -> None:
        if self.busy:
            return
        row = self.tree.focus()
        if row in self.items:
            self._toggle_tree_rows_like(row)

    def selected_item(self) -> UpdateItem | None:
        selection = self.tree.selection()
        if selection and selection[0] in self.items:
            return self.items[str(selection[0])]
        focused = self.tree.focus()
        if focused in self.items:
            return self.items[focused]
        return None

    def focused_or_selected_item(self) -> UpdateItem | None:
        focused = self.tree.focus()
        if focused in self.items:
            return self.items[focused]
        return self.selected_item()

    def show_focused_or_selected_details(self) -> None:
        item = self.focused_or_selected_item()
        if item is None:
            self._notify_user("Select one package first.", summary="Select one package first")
            return
        self.show_item_details(item)

    def show_item_details(self, item: UpdateItem, *, reuse_quick_window: bool = False) -> None:
        if reuse_quick_window and self._quick_details_window is not None:
            quick_window = self._quick_details_window
            try:
                quick_window_exists = bool(quick_window.winfo_exists())
            except Exception:
                quick_window_exists = False
            if quick_window_exists and self._quick_details_refresh:
                self._quick_details_refresh(item)
                with contextlib.suppress(Exception):
                    quick_window.deiconify()
                    quick_window.lift()
                    quick_window.focus_set()
                return
            self._quick_details_window = None
            self._quick_details_refresh = None
        tk, ttk = self.tk, self.ttk
        px = self.visuals.px
        current_item = item
        details_icon_request = 0
        details_icon_after_id: str | None = None
        details_icon_paint_after_id: str | None = None
        details_tree_sync_after_id: str | None = None
        gallery_prefetch_after_id: str | None = None
        pending_tree_sync_key = ""
        pending_icon_presentation: tuple[int, Any] | None = None
        header_layout_state: tuple[bool, bool] | None = None
        current_icon_evidence: dict[str, Any] | None = None
        current_generated_icon_path: Path | None = None
        window = self._create_toplevel(self.root)
        details_icon_stream = f"details-window:{id(window)}"
        window.title(f"Package details - {item.name}")
        window.geometry(self.visuals.geometry_from_dips("780x520"))
        window.transient(self.root)
        frame = ttk.Frame(window, padding=px(16))
        frame.pack(fill="both", expand=True)
        header = ttk.Frame(frame)
        header.pack(fill="x", pady=(0, px(10)))
        title_block = ttk.Frame(header)
        icon_label = tk.Label(
            header,
            bd=0,
            highlightthickness=0,
        )
        self._register_theme_widget(icon_label, background="window")
        icon_label.image = None

        def refresh_icon_cursor() -> None:
            ready = current_generated_icon_path is not None
            icon_label.configure(cursor="hand2" if ready else "")

        def show_icon_context_menu(event: Any) -> str:
            menu = self._new_context_menu(icon_label)
            generated_path = current_generated_icon_path
            menu.add_command(
                label="Save generated PNG as…",
                command=lambda: self._save_generated_icon_as(
                    current_item,
                    generated_path,
                    parent=window,
                ),
                state=(
                    "normal"
                    if generated_path is not None and generated_path.exists()
                    else "disabled"
                ),
            )
            try:
                menu.tk_popup(int(event.x_root), int(event.y_root))
            finally:
                menu.grab_release()
            return "break"

        icon_label.bind("<Button-3>", show_icon_context_menu, add="+")

        def schedule_gallery_prefetch(_event: Any = None) -> None:
            nonlocal gallery_prefetch_after_id
            if gallery_prefetch_after_id is not None:
                with contextlib.suppress(tk.TclError):
                    window.after_cancel(gallery_prefetch_after_id)
                gallery_prefetch_after_id = None
            if not self._icon_gallery_discovered:
                return
            snapshot = dataclasses.replace(current_item)

            def start_prefetch() -> None:
                nonlocal gallery_prefetch_after_id
                gallery_prefetch_after_id = None
                try:
                    if not window.winfo_exists() or snapshot.key != current_item.key:
                        return
                except tk.TclError:
                    return
                self._prepare_icon_gallery_session(snapshot)

            gallery_prefetch_after_id = window.after(1000, start_prefetch)

        def show_icon_gallery_from_label(_event: Any = None) -> str:
            first_discovery = not self._icon_gallery_discovered
            self._icon_gallery_discovered = True
            if first_discovery:
                self.logger.event(
                    "icon_gallery_discovered",
                    item=item_diagnostic_fields(current_item),
                )
            schedule_gallery_prefetch()
            self.show_icon_gallery(current_item, parent=window)
            return "break"

        icon_label.bind("<Double-Button-1>", show_icon_gallery_from_label, add="+")
        self._bind_widget_tooltip(
            icon_label,
            "Double-click to open the local icon lineup. "
            "Right-click to save the final processed PNG.",
        )
        title_label = ttk.Label(
            title_block,
            text=item.name,
            font=self._ui_font(15, semibold=True, display=True),
        )
        title_label.pack(anchor="w")
        subtitle_label = ttk.Label(
            title_block,
            text="Read-only identity, scope, and update evidence for this exact package.",
            style="Subtitle.TLabel",
        )
        subtitle_label.pack(anchor="w", pady=(px(2), 0))

        def layout_header(_event: Any = None) -> None:
            nonlocal header_layout_state
            layout_state = (
                icon_label.image is not None,
                header.winfo_width() >= px(620),
            )
            if layout_state == header_layout_state:
                return
            header_layout_state = layout_state
            title_block.pack_forget()
            icon_label.pack_forget()
            if layout_state == (True, True):
                icon_label.pack(side="right", anchor="ne", padx=(px(14), 0))
                title_block.pack(side="left", fill="x", expand=True, anchor="nw")
            else:
                if layout_state[0]:
                    icon_label.pack(anchor="w", pady=(0, px(8)))
                title_block.pack(fill="x", anchor="w")

        header.bind("<Configure>", layout_header, add="+")
        header.after_idle(layout_header)
        text_frame = ttk.Frame(frame)
        text_frame.pack(fill="both", expand=True)
        text = tk.Text(
            text_frame,
            wrap="word",
            font=self._mono_font(9),
            height=20,
            relief="solid",
            borderwidth=1,
        )
        self._configure_text_panel(text)
        yscroll = ttk.Scrollbar(text_frame, orient="vertical", command=text.yview)
        text.configure(yscrollcommand=yscroll.set)
        text.grid(row=0, column=0, sticky="nsew")
        yscroll.grid(row=0, column=1, sticky="ns")
        text_frame.columnconfigure(0, weight=1)
        text_frame.rowconfigure(0, weight=1)
        text.configure(state="disabled")
        buttons = ttk.Frame(frame)
        buttons.pack(fill="x", pady=(px(10), 0))
        copy_button = self._button(
            buttons,
            text="Copy details",
            command=lambda: self._copy_text(
                self.item_details_text(current_item, icon_evidence=current_icon_evidence),
                log_message=f"Copied details for {current_item.name}",
            ),
            tooltip="Copy this package's full evidence text for a maintainer or LLM.",
        )
        copy_button.pack(side="left", padx=(0, px(8)))
        guided_button = self._button(
            buttons,
            text="Copy guided commands",
            command=lambda: self._copy_text(powershell_preview_migration_guidance(current_item)),
            tooltip=(
                "Copy the safe manual PowerShell Preview migration commands. "
                "This does not run them."
            ),
        )
        repair_button = self._button(
            buttons,
            text="Create repair script…",
            command=lambda: self._create_winget_repair_script(current_item),
            tooltip=(
                "Create a reviewable administrator .cmd for this exact WinGet package "
                "folder. It takes ownership, restores inherited permissions, grants your "
                "normal Windows account Full Control, and attempts to restore ownership. "
                "It is never run automatically and does not install, uninstall, or update "
                "the package."
            ),
        )
        self._button(
            buttons,
            text="Close",
            command=window.destroy,
            tooltip="Close this details window.",
        ).pack(side="right")

        def visible_neighbor(direction: int) -> UpdateItem | None:
            rows = [str(row) for row in self.tree.get_children() if str(row) in self.items]
            if not rows or current_item.key not in rows:
                return None
            index = rows.index(current_item.key) + direction
            if index < 0 or index >= len(rows):
                return None
            return self.items.get(rows[index])

        def refresh_details(next_item: UpdateItem) -> None:
            nonlocal current_generated_icon_path, current_icon_evidence, current_item
            nonlocal details_icon_after_id, details_icon_request, details_tree_sync_after_id
            nonlocal pending_tree_sync_key
            current_item = next_item
            details_icon_request += 1
            request_id = details_icon_request
            if details_icon_after_id is not None:
                with contextlib.suppress(self.tk.TclError):
                    window.after_cancel(details_icon_after_id)
                details_icon_after_id = None
            window.title(f"Package details - {current_item.name}")
            title_label.configure(text=current_item.name)
            details_icon_size = max(48, self.visuals.px(DETAIL_ICON_SIZE_DIP))
            icon_image = self._details_icon_image_if_ready(current_item, details_icon_size)
            current_icon_evidence = self._details_icon_evidence(current_item, details_icon_size)
            current_generated_icon_path = (
                Path(str(current_icon_evidence["generated_png"]))
                if current_icon_evidence is not None
                else None
            )
            needs_icon_prepare = icon_image is None or not bool(
                current_icon_evidence and current_icon_evidence.get("metadata_ready")
            )
            if preferred_vector_style(current_item):
                needs_icon_prepare = False
            if icon_image is None:
                icon_image, generated_fallback = self._details_icon_placeholder(
                    current_item, details_icon_size,
                )
                if generated_fallback:
                    current_icon_evidence = self._details_icon_evidence(
                        current_item, details_icon_size, generated_fallback=True,
                    )
                    current_generated_icon_path = Path(str(current_icon_evidence["generated_png"]))

            def present_icon(image: Any) -> None:
                """Coalesce key-repeat paints and force only the newest icon through Tk's idle queue."""

                nonlocal details_icon_paint_after_id, pending_icon_presentation
                pending_icon_presentation = (request_id, image)
                if details_icon_paint_after_id is not None:
                    return

                def flush_icon_presentation() -> None:
                    nonlocal details_icon_paint_after_id, pending_icon_presentation
                    details_icon_paint_after_id = None
                    presentation = pending_icon_presentation
                    pending_icon_presentation = None
                    if presentation is None or presentation[0] != details_icon_request:
                        return
                    try:
                        if not window.winfo_exists():
                            return
                    except self.tk.TclError:
                        return
                    latest_image = presentation[1]
                    icon_label.configure(image=latest_image or "")
                    icon_label.image = latest_image
                    refresh_icon_cursor()
                    layout_header()

                details_icon_paint_after_id = window.after(1, flush_icon_presentation)

            if needs_icon_prepare:

                def apply_prepared_icon(item_key: str) -> None:
                    nonlocal current_generated_icon_path, current_icon_evidence
                    try:
                        window_exists = bool(window.winfo_exists())
                    except self.tk.TclError:
                        return
                    if (
                        not window_exists
                        or details_icon_request != request_id
                        or current_item.key != item_key
                    ):
                        return
                    prepared_item = self.items.get(item_key)
                    if prepared_item is None:
                        return
                    prepared_image = self._details_icon_image_if_ready(
                        prepared_item, details_icon_size
                    )
                    if prepared_image is None:
                        return
                    current_icon_evidence = self._details_icon_evidence(
                        prepared_item, details_icon_size
                    )
                    current_generated_icon_path = (
                        Path(str(current_icon_evidence["generated_png"]))
                        if current_icon_evidence is not None
                        else None
                    )
                    refresh_icon_cursor()
                    present_icon(prepared_image)
                    reading_position = text.yview()
                    selected_text = text.tag_ranges("sel")
                    text.configure(state="normal")
                    text.delete("1.0", "end")
                    text.insert(
                        "1.0",
                        self.item_details_text(
                            current_item,
                            icon_evidence=current_icon_evidence,
                        ),
                    )
                    text.configure(state="disabled")
                    text.yview_moveto(reading_position[0])
                    if selected_text:
                        text.tag_add("sel", *selected_text)

                def queue_prepared_icon() -> None:
                    nonlocal details_icon_after_id
                    details_icon_after_id = None
                    try:
                        window_exists = bool(window.winfo_exists())
                    except self.tk.TclError:
                        return
                    if (
                        not window_exists
                        or details_icon_request != request_id
                        or current_item.key != next_item.key
                    ):
                        return
                    self._queue_details_icon_prepare(
                        current_item,
                        details_icon_size,
                        apply_prepared_icon,
                        coalesce_key=details_icon_stream,
                    )

                details_icon_after_id = window.after(
                    DETAIL_ICON_NAVIGATION_SETTLE_MS,
                    queue_prepared_icon,
                )
            present_icon(icon_image)
            text.configure(state="normal")
            text.delete("1.0", "end")
            text.insert(
                "1.0",
                self.item_details_text(current_item, icon_evidence=current_icon_evidence),
            )
            text.configure(state="disabled")
            if is_powershell_preview_msi_migration(current_item):
                if not guided_button.winfo_ismapped():
                    guided_button.pack(side="left")
            else:
                guided_button.pack_forget()
            hold_record = self.settings.data.get("attempt_holds", {}).get(
                current_item.candidate_key
            )
            if winget_permission_repair_target(current_item, hold_record) is not None:
                repair_button.configure(state="disabled" if self.busy else "normal")
                if not repair_button.winfo_ismapped():
                    repair_button.pack(side="left")
            else:
                repair_button.pack_forget()
            pending_tree_sync_key = current_item.key
            with contextlib.suppress(Exception):
                self.tree.selection_set(current_item.key)
                self.tree.focus(current_item.key)

            def sync_main_tree() -> None:
                nonlocal details_tree_sync_after_id, pending_tree_sync_key
                details_tree_sync_after_id = None
                item_key = pending_tree_sync_key
                pending_tree_sync_key = ""
                if not item_key:
                    return
                with contextlib.suppress(Exception):
                    self.tree.see(item_key)

            # Selection is immediate; only viewport scrolling is coalesced to
            # the newest row once per display frame. This keeps the blue line
            # visibly tracking key-repeat without starving the Details icon.
            if details_tree_sync_after_id is None:
                details_tree_sync_after_id = window.after(16, sync_main_tree)
            schedule_gallery_prefetch()

        def cycle_details(direction: int) -> str:
            next_item = visible_neighbor(direction)
            if next_item is not None:
                refresh_details(next_item)
            return "break"

        if reuse_quick_window:
            self._quick_details_window = window
            self._quick_details_refresh = refresh_details

            def clear_quick_details_reference(_event: Any = None) -> None:
                if _event is not None and _event.widget is not window:
                    return
                if self._quick_details_window is window:
                    self._quick_details_window = None
                    self._quick_details_refresh = None

            window.bind("<Destroy>", clear_quick_details_reference, add="+")

        def apply_live_refinement(item_key: str) -> None:
            if item_key and current_item.key != item_key:
                return
            live_item = (self.items.get(current_item.key)
                         or self._scan_view_items[True].get(current_item.key)
                         or self._scan_view_items[False].get(current_item.key))
            if live_item is None:
                title_label.configure(text=current_item.name + " — no longer in current inventory")
                return
            if not item_key and live_item is current_item:
                return
            position = text.yview()[0]
            refresh_details(live_item)
            text.yview_moveto(position)

        self._details_refinement_listeners.append(apply_live_refinement)

        def clear_refinement_listener(event: Any) -> None:
            if event.widget is not window:
                return
            with contextlib.suppress(ValueError):
                self._details_refinement_listeners.remove(apply_live_refinement)

        window.bind("<Destroy>", clear_refinement_listener, add="+")

        def cancel_details_callbacks(event: Any) -> None:
            nonlocal details_icon_after_id, details_icon_paint_after_id
            nonlocal details_tree_sync_after_id, gallery_prefetch_after_id
            nonlocal pending_icon_presentation
            if event.widget is not window:
                return
            for after_id in (
                details_icon_after_id,
                details_icon_paint_after_id,
                details_tree_sync_after_id,
                gallery_prefetch_after_id,
            ):
                if after_id is not None:
                    with contextlib.suppress(self.tk.TclError):
                        window.after_cancel(after_id)
            details_icon_after_id = None
            details_icon_paint_after_id = None
            details_tree_sync_after_id = None
            gallery_prefetch_after_id = None
            pending_icon_presentation = None

        window.bind("<Destroy>", cancel_details_callbacks, add="+")

        refresh_details(item)
        window.bind("<Left>", lambda _event: cycle_details(-1), add="+")
        window.bind("<Right>", lambda _event: cycle_details(1), add="+")
        window.bind("<Configure>", schedule_gallery_prefetch, add="+")
        window.bind("<KeyPress>", schedule_gallery_prefetch, add="+")
        text.bind("<Left>", lambda _event: cycle_details(-1), add="+")
        text.bind("<Right>", lambda _event: cycle_details(1), add="+")
        text.bind("<MouseWheel>", schedule_gallery_prefetch, add="+")

    def _save_generated_icon_as(
        self,
        item: UpdateItem,
        generated_path: Path | None,
        *,
        parent: Any,
    ) -> None:
        if generated_path is None or not generated_path.exists():
            self._notify_user(
                f"The generated icon for {item.name} is not ready yet.",
                level="warning",
                summary="Generated icon is still being prepared",
            )
            return
        safe_name = re.sub(r"[^A-Za-z0-9 _.-]+", "-", item.name).strip(" .-") or "package-icon"
        destination_text = self.filedialog.asksaveasfilename(
            parent=parent,
            title=f"Save generated icon for {item.name}",
            defaultextension=".png",
            initialfile=f"{safe_name}.png",
            filetypes=(("PNG image", "*.png"), ("All files", "*.*")),
        )
        if not destination_text:
            return
        destination = Path(destination_text)
        try:
            if destination.resolve() != generated_path.resolve():
                shutil.copyfile(generated_path, destination)
            self._append_log(f"Saved generated icon for {item.name}: {destination}")
            self.logger.event(
                "generated_icon_saved",
                item=item_diagnostic_fields(item),
                source_path=str(generated_path),
                destination_path=str(destination),
            )
            self.summary_var.set(f"Saved generated icon for {item.name}")
        except OSError as exc:
            self._notify_user(
                f"Could not save the generated icon for {item.name}: {exc}",
                level="error",
                summary="Could not save generated icon",
            )

    def _icon_gallery_source_paths(self, item: UpdateItem) -> tuple[Path, ...]:
        """Return a small, package-bound set of plausible artwork containers."""

        candidates: dict[str, Path] = {}

        def add(path: Path | None) -> None:
            if path is None:
                return
            with contextlib.suppress(OSError):
                if path.is_file():
                    candidates.setdefault(os.path.normcase(str(path.resolve())), path)

        primary = self._known_item_icon_source_path(item) or self._item_icon_source_path(item)
        add(primary)
        if item.icon_source:
            add(resolve_indirect_icon_path(item.icon_source))
            add(Path(strip_display_icon_index(item.icon_source)))
        if primary is not None and primary.suffix.casefold() == ".png":
            for variant in _appx_gallery_variant_sample(
                primary,
                _appx_asset_variants(primary),
            ):
                add(variant)

        location_text = os.path.expandvars(item.installed_location.strip().strip('"'))
        location = Path(location_text) if location_text else None
        if location is not None and location.is_dir():
            app_name = normalized_package_name(item.name)
            primary_stem = normalized_package_name(primary.stem) if primary is not None else ""
            visited = 0
            pending: deque[tuple[Path, int]] = deque(((location, 0),))
            plausible: list[tuple[int, int, str, Path]] = []
            while pending and visited < 240:
                directory, depth = pending.popleft()
                try:
                    entries = list(directory.iterdir())
                except OSError:
                    continue
                for path in entries:
                    visited += 1
                    if visited > 240:
                        break
                    with contextlib.suppress(OSError):
                        if path.is_dir():
                            if depth < 1 and path.name.casefold() not in {
                                "locales",
                                "node_modules",
                                "plugins",
                                "resources",
                            }:
                                pending.append((path, depth + 1))
                            continue
                        if not path.is_file() or path.suffix.casefold() not in {
                            ".dll",
                            ".exe",
                            ".ico",
                            ".png",
                        }:
                            continue
                        stem = normalized_package_name(path.stem)
                        app_overlap = bool(
                            len(stem) >= 4
                            and len(app_name) >= 4
                            and (stem in app_name or app_name in stem)
                        )
                        primary_overlap = bool(
                            len(stem) >= 3
                            and len(primary_stem) >= 3
                            and len(os.path.commonprefix((stem, primary_stem))) >= 3
                        )
                        if app_overlap or primary_overlap:
                            plausible.append(
                                (
                                    0 if path.suffix.casefold() in {".ico", ".png"} else 1,
                                    depth,
                                    path.name.casefold(),
                                    path,
                                )
                            )
            for _kind, _depth, _name, path in sorted(plausible)[:10]:
                add(path)
        return tuple(candidates.values())[:16]

    def _discard_icon_gallery_preparation(self, item_key: str) -> None:
        prepared = self._icon_gallery_preparations.pop(item_key, None)
        if prepared is None:
            return
        bundle = prepared.get("bundle")
        if isinstance(bundle, IconGalleryMemoryBundle):
            self._icon_gallery_bundle_bytes = max(
                0, self._icon_gallery_bundle_bytes - len(bundle.payload)
            )

    def _trim_icon_gallery_preparations(self, budget: int | None = None) -> None:
        if budget is None:
            available = available_physical_memory_bytes()
            budget = min(128 * 1024**2, max(16 * 1024**2, (available or 256 * 1024**2) // 16))
        def retained_bytes(prepared: Mapping[str, Any]) -> int:
            bundle = prepared.get("bundle")
            return (len(bundle.payload) if isinstance(bundle, IconGalleryMemoryBundle) else 0) + sum(
                len(data) for _record, data in prepared.get("items", ())
            )
        total = sum(retained_bytes(prepared) for prepared in self._icon_gallery_preparations.values())
        while total > budget and self._icon_gallery_preparations:
            oldest = next(iter(self._icon_gallery_preparations))
            total -= retained_bytes(self._icon_gallery_preparations[oldest])
            self._discard_icon_gallery_preparation(oldest)

    def _discard_wrench_gallery(self, item_key: str) -> None:
        """Once genuine artwork is ready, retain no package-local wrench reference."""
        prepared = getattr(self, "_icon_gallery_preparations", {}).get(item_key)
        if prepared and prepared.get("fallback_wrench"):
            self._discard_icon_gallery_preparation(item_key)
        colors = getattr(self, "_icon_sort_colors", {})
        if item_key in colors and colors[item_key][0][:2] == (0, "wrench"):
            colors.pop(item_key)

    def _gallery_vector_style(self, item: UpdateItem) -> str:
        style = fallback_vector_style(item)
        if not preferred_vector_style(item) and (
            self._has_real_icon_source(item)
            or any(key[0] == item.key for key in self._details_icon_images)
        ):
            return ""
        return style

    def _icon_gallery_preparations_at_capacity(
        self,
        *,
        available_memory: int | None = None,
    ) -> bool:
        """Keep speculative raw galleries within the current RAM-aware allowance."""

        if available_memory is None:
            available_memory = available_physical_memory_bytes()
        capacity = icon_gallery_prefetch_capacity(
            len(self.items),
            available_memory=available_memory,
        )
        retained_or_pending = len(self._icon_gallery_preparations) + len(
            self._icon_gallery_inflight
        )
        return retained_or_pending >= capacity

    def _report_icon_gallery_memory_growth(self) -> None:
        threshold = self._icon_gallery_bundle_report_threshold
        if self._icon_gallery_bundle_bytes < threshold:
            return
        crossed = threshold
        while self._icon_gallery_bundle_bytes >= self._icon_gallery_bundle_report_threshold:
            crossed = self._icon_gallery_bundle_report_threshold
            self._icon_gallery_bundle_report_threshold *= 2
        total_mib = self._icon_gallery_bundle_bytes / 1024**2
        self._append_log(
            f"Icon Lineup raw bundle RAM: {total_mib:.1f} MiB "
            f"({len(self._icon_gallery_preparations)} package galleries; passed "
            f"{crossed // 1024**2} MiB)"
        )
        self.logger.event(
            "icon_gallery_memory_threshold_crossed",
            raw_bundle_bytes=self._icon_gallery_bundle_bytes,
            package_galleries=len(self._icon_gallery_preparations),
            threshold_bytes=crossed,
        )

    def _adjust_icon_gallery_blit_memory(self, delta: int) -> None:
        """Track decoded Tk images retained for instant lineup revisits."""

        self._icon_gallery_blit_bytes = max(0, self._icon_gallery_blit_bytes + delta)
        threshold = self._icon_gallery_blit_report_threshold
        if self._icon_gallery_blit_bytes < threshold:
            return
        crossed = threshold
        while self._icon_gallery_blit_bytes >= self._icon_gallery_blit_report_threshold:
            crossed = self._icon_gallery_blit_report_threshold
            self._icon_gallery_blit_report_threshold *= 2
        if not self.debug_mode:
            return
        total_mib = self._icon_gallery_blit_bytes / 1024**2
        self._append_log(
            f"Icon Lineup estimated fast-blit image RAM: {total_mib:.1f} MiB decoded "
            f"(passed {crossed // 1024**2} MiB)"
        )
        self.logger.event(
            "icon_gallery_blit_memory_threshold_crossed",
            estimated_decoded_image_bytes=self._icon_gallery_blit_bytes,
            threshold_bytes=crossed,
        )

    def _cached_icon_gallery_image(
        self,
        key: tuple[bytes, int],
        factory: Callable[[], Any],
    ) -> Any:
        """Return a decoded Tk image, retaining it when safe RAM headroom allows."""

        cached = self._icon_gallery_blit_cache.get(key)
        if cached is not None:
            self._icon_gallery_blit_cache.move_to_end(key)
            return cached[0]
        image = factory()
        estimated_bytes = max(1, int(image.width())) * max(1, int(image.height())) * 4
        if estimated_bytes <= self._icon_gallery_blit_limit:
            while (
                self._icon_gallery_blit_cache
                and self._icon_gallery_blit_bytes + estimated_bytes
                > self._icon_gallery_blit_limit
            ):
                _discarded_key, (_discarded_image, discarded_bytes) = (
                    self._icon_gallery_blit_cache.popitem(last=False)
                )
                self._adjust_icon_gallery_blit_memory(-discarded_bytes)
            self._icon_gallery_blit_cache[key] = (image, estimated_bytes)
            self._adjust_icon_gallery_blit_memory(estimated_bytes)
        return image

    def _displayable_icon_gallery_items(self, item, items):
        """Use embedded artwork when every retrieved image fails native decoding."""
        tk = self.tk
        px = self.visuals.px
        # A PNG header alone does not establish that Tk can display it.
        # Sparse MSIX identities can ship an unreadable 1-pixel placeholder.
        displayable_items = []
        for record, png_data in items:
            if png_dimensions_fast(png_data) == (1, 1):
                continue
            if (not record.get("generated_vector")
                    and ("transparent_coverage" not in record or record["transparent_coverage"] == 1.0)):
                decoded = read_png_rgba(png_data)
                if decoded is not None and not any(any(row[3::4]) for row in decoded[2]):
                    continue
            try:
                self._cached_icon_gallery_image(
                    (hashlib.sha256(png_data).digest(), 1),
                    lambda data=png_data: tk.PhotoImage(data=data, format="png"),
                )
            except (ValueError, tk.TclError):
                continue
            displayable_items.append((record, png_data))
        items = displayable_items or vector_gallery_records(
            fallback_vector_style(item),
            (max(12, px(PACKAGE_ICON_SIZE_DIP)), max(48, px(DETAIL_ICON_SIZE_DIP)), 512),
        )
        return items

    def _queue_icon_gallery_photo_decode(
        self,
        items: Sequence[tuple[Mapping[str, Any], bytes]],
        *,
        prioritize: bool = False,
    ) -> None:
        """Warm native Tk image handles in short, directional idle-time slices."""

        queued: list[tuple[tuple[bytes, int], bytes]] = []
        for _record, png_data in items:
            dimensions = png_dimensions_fast(png_data)
            if dimensions is None:
                continue
            estimated_bytes = dimensions[0] * dimensions[1] * 4
            if self._icon_gallery_blit_bytes + estimated_bytes > self._icon_gallery_blit_limit:
                continue
            key = (hashlib.sha256(png_data).digest(), 1)
            if key in self._icon_gallery_blit_cache or key in self._icon_gallery_photo_decode_pending:
                continue
            self._icon_gallery_photo_decode_pending.add(key)
            queued.append((key, png_data))
        if queued and not self._icon_gallery_blit_warmup_announced:
            self._icon_gallery_blit_warmup_announced = True
            if self.debug_mode:
                self._append_log(
                    "Icon Lineup fast-blit cache warming: "
                    f"{self._icon_gallery_blit_bytes / 1024**2:.1f} MiB decoded; "
                    f"RAM-aware ceiling {self._icon_gallery_blit_limit / 1024**2:.0f} MiB"
                )
        if prioritize:
            # A newly requested Lineup must jump ahead of speculative deep
            # prefetch while preserving its own smallest-to-largest order.
            self._icon_gallery_photo_decode_queue.extendleft(reversed(queued))
        else:
            self._icon_gallery_photo_decode_queue.extend(queued)
        if self._icon_gallery_photo_decode_queue and self._icon_gallery_photo_decode_after_id is None:
            self._icon_gallery_photo_decode_after_id = self.root.after(
                1, self._pump_icon_gallery_photo_decode
            )

    def _pump_icon_gallery_photo_decode(self) -> None:
        self._icon_gallery_photo_decode_after_id = None
        deadline = (
            time.perf_counter() + ICON_GALLERY_PHOTO_DECODE_TIME_BUDGET_SECONDS
        )
        decoded = 0
        while self._icon_gallery_photo_decode_queue and decoded < 2:
            key, png_data = self._icon_gallery_photo_decode_queue.popleft()
            self._icon_gallery_photo_decode_pending.discard(key)
            if key in self._icon_gallery_blit_cache:
                continue
            try:
                self._cached_icon_gallery_image(
                    key,
                    lambda data=png_data: self.tk.PhotoImage(data=data, format="png"),
                )
            except (ValueError, self.tk.TclError):
                continue
            decoded += 1
            if time.perf_counter() >= deadline:
                break
        if self._icon_gallery_photo_decode_queue and not self._closing:
            self._icon_gallery_photo_decode_after_id = self.root.after(
                1, self._pump_icon_gallery_photo_decode
            )

    def _prepare_icon_gallery_session(
        self,
        item: UpdateItem,
        callback: Callable[[IconGalleryMemoryBundle, str], None] | None = None,
    ) -> None:
        """Prepare one raw session-memory gallery off Tk's thread."""

        if self._closing:
            return
        if callback is None and self._icon_gallery_preparations_at_capacity():
            return
        snapshot = dataclasses.replace(item)
        details_rendition: dict[str, str] = {}
        details_display_path: Path | None = None
        details_size = max(48, self.visuals.px(DETAIL_ICON_SIZE_DIP))
        vector_style = self._gallery_vector_style(snapshot)
        vector_sizes = (max(12, self.visuals.px(PACKAGE_ICON_SIZE_DIP)), details_size, 512)
        vector_generation = self._icon_prepare_generation
        details_source = None if preferred_vector_style(snapshot) else self._known_item_icon_source_path(snapshot)
        if details_source is not None:
            details_raw_path = self._details_icon_cache_path(
                snapshot,
                details_source,
                details_size,
            )
            details_display_path = self._display_icon_cache_path(
                details_raw_path,
                details_size,
            )
            # The worker owns the disk check. Deep gallery prefetch can touch
            # hundreds of items and must not turn Tk's thread into a stat loop.
            details_rendition = {
                "path": str(details_display_path),
                "source": str(details_source),
            }
        signature = (
            *item_icon_identity(snapshot),
            snapshot.current,
            ICON_GALLERY_POLICY_REVISION,
            str(vector_bitmap_cache_path(vector_style, details_size)) if vector_style and vector_style != "wrench" else "",
            str(details_display_path or ""),
            bool(vector_style),
        )
        prepared = self._icon_gallery_preparations.get(snapshot.key)
        if prepared is not None and prepared.get("signature") == signature:
            rendition_became_ready = (
                callback is not None
                and details_display_path is not None
                and not bool(prepared.get("details_rendition_included"))
                and details_display_path.is_file()
            )
            if rendition_became_ready:
                self._discard_icon_gallery_preparation(snapshot.key)
                prepared = None
        if prepared is not None and prepared.get("signature") == signature:
            if callback is not None:
                # This method is entered from Tk callbacks. A warm Lineup can
                # therefore present immediately: no worker, pipe, decode, or
                # extra event-loop turn on Ctrl+Arrow navigation.
                self._icon_gallery_preparations.pop(snapshot.key)
                self._icon_gallery_preparations[snapshot.key] = prepared
                callback(prepared["bundle"], str(prepared.get("error", "")))
            return
        if prepared is not None:
            self._discard_icon_gallery_preparation(snapshot.key)
        callbacks = self._icon_gallery_inflight.get(snapshot.key)
        if callbacks is not None:
            if callback is not None:
                callbacks.append(callback)
                self._promote_icon_gallery_job(snapshot.key)
            return
        callbacks = []
        if callback is not None:
            callbacks.append(callback)
        self._icon_gallery_inflight[snapshot.key] = callbacks

        def worker() -> None:
            error = ""
            included_style = vector_style
            bundle = IconGalleryMemoryBundle(b"", 0)
            unpacked_items: list[tuple[dict[str, Any], bytes]] = []
            sources: tuple[Path, ...] = ()
            try:
                sources = self._icon_gallery_source_paths(snapshot)
                if sources or details_rendition:
                    completed = subprocess.run(
                        cached_self_command("--icon-gallery-worker"),
                        input=json.dumps(
                            {"sources": [str(path) for path in sources], "details_rendition": details_rendition}
                        ).encode("utf-8"),
                        stdout=subprocess.PIPE,
                        stderr=subprocess.DEVNULL,
                        timeout=120,
                        check=False,
                        cwd=str(SCRIPT_PATH.parent),
                        creationflags=CREATE_NO_WINDOW | BELOW_NORMAL_PRIORITY_CLASS,
                    )
                    if completed.returncode != 0:
                        error = f"helper exited with code {completed.returncode}"
                    elif len(completed.stdout) > MAX_ICON_GALLERY_BUNDLE_BYTES:
                        error = "helper response was unexpectedly large"
                    else:
                        bundle = deserialize_icon_gallery_bundle(completed.stdout)
                        unpacked_items = bundle.unpack()
            except Exception as exc:
                # A worker failure must still release its callback ownership.
                error = f"{type(exc).__name__}: {exc}"
            try:
                if included_style and not preferred_vector_style(snapshot) and any(
                    not record.get("generic_shell_fallback") for record, _png in unpacked_items
                ):
                    included_style = ""
                generated = []
                if included_style:
                    self._cache_vector_bitmaps((included_style,), vector_sizes, vector_generation)
                    generated = vector_gallery_records(included_style, vector_sizes)
                if generated:
                    # Keep the usable replacement, not Windows' identical generic
                    # rendition in every package's packed gallery/cache stack.
                    unpacked_items = [pair for pair in unpacked_items
                                      if not pair[0].get("generic_shell_fallback")]
                unpacked_items = unpacked_items[-(MAX_ICON_GALLERY_RESULTS-len(generated)):]
                bundle = pack_icon_gallery_memory_items(unpacked_items, shared_items=generated)
                unpacked_items += generated
                unpacked_items.sort(key=lambda pair: (
                    max(int(pair[0]["width"]), int(pair[0]["height"])), bool(pair[0].get("generated_vector"))
                ))
            except Exception as exc:
                error = error or f"Generated artwork: {exc}"

            def finish() -> None:
                if self._icon_gallery_inflight.get(snapshot.key) is not callbacks:
                    return
                pending_callbacks = self._icon_gallery_inflight.pop(snapshot.key, [])
                if self._closing:
                    return
                if included_style and self._gallery_vector_style(snapshot) != included_style:
                    # Artwork arrived while this worker was preparing the old fallback.
                    # Do not publish that obsolete reference, including to an open Lineup.
                    for pending_callback in pending_callbacks:
                        self._prepare_icon_gallery_session(self.items.get(snapshot.key, snapshot), pending_callback)
                    return
                self._discard_icon_gallery_preparation(snapshot.key)
                self._icon_gallery_preparations[snapshot.key] = {
                    "signature": signature,
                    "bundle": bundle,
                    "items": tuple(unpacked_items),
                    "details_rendition_included": any(
                        bool(record.get("package_details_rendition"))
                        for record, _png_data in unpacked_items
                    ),
                    "error": error,
                    "fallback_wrench": included_style == "wrench",
                }
                self._icon_gallery_bundle_bytes += len(bundle.payload)
                self._report_icon_gallery_memory_growth()
                self._trim_icon_gallery_preparations()
                self._queue_icon_gallery_photo_decode(
                    unpacked_items,
                    prioritize=bool(pending_callbacks),
                )
                self.logger.event(
                    "icon_gallery_prepared",
                    item=item_diagnostic_fields(snapshot),
                    representations=bundle.item_count,
                    source_count=len(sources),
                    cache_format="raw-memory",
                    raw_bundle_bytes=bundle.raw_size,
                    error=error,
                )
                for pending_callback in pending_callbacks:
                    with contextlib.suppress(Exception):
                        pending_callback(bundle, error)

            if self._closing:
                return
            self.events.put(("ui_callback", (finish, ())))

        self._enqueue_icon_gallery_job(
            snapshot.key,
            worker,
            foreground=callback is not None,
        )

    def _enqueue_icon_gallery_job(
        self,
        item_key: str,
        worker: Callable[[], None],
        *,
        foreground: bool,
    ) -> None:
        """Feed at most two gallery helpers, with visible requests ahead of look-ahead."""

        self._icon_gallery_job_sequence += 1
        sequence = self._icon_gallery_job_sequence
        priority = 0 if foreground else 10
        self._icon_gallery_queued_jobs[item_key] = (priority, sequence, worker)
        heapq.heappush(self._icon_gallery_job_heap, (priority, sequence, item_key))
        self._pump_icon_gallery_jobs()

    def _promote_icon_gallery_job(self, item_key: str) -> None:
        queued = self._icon_gallery_queued_jobs.get(item_key)
        if queued is None or queued[0] == 0:
            return
        _priority, _sequence, worker = queued
        self._icon_gallery_job_sequence += 1
        sequence = self._icon_gallery_job_sequence
        self._icon_gallery_queued_jobs[item_key] = (0, sequence, worker)
        heapq.heappush(self._icon_gallery_job_heap, (0, sequence, item_key))
        self._pump_icon_gallery_jobs()

    def _pump_icon_gallery_jobs(self) -> None:
        while not self._closing and self._icon_gallery_active_jobs < 2 and self._icon_gallery_job_heap:
            priority, sequence, item_key = heapq.heappop(self._icon_gallery_job_heap)
            queued = self._icon_gallery_queued_jobs.get(item_key)
            if queued is None or queued[:2] != (priority, sequence):
                continue
            _priority, _sequence, worker = self._icon_gallery_queued_jobs.pop(item_key)
            self._icon_gallery_active_jobs += 1

            def run_job(job: Callable[[], None] = worker) -> None:
                try:
                    job()
                finally:
                    if not self._closing:
                        self.events.put(
                            ("ui_callback", (self._finish_icon_gallery_job, ()))
                        )

            threading.Thread(
                target=run_job,
                name=f"wdp-icon-gallery-{self._icon_gallery_active_jobs}",
                daemon=True,
            ).start()

    def _finish_icon_gallery_job(self) -> None:
        self._icon_gallery_active_jobs = max(0, self._icon_gallery_active_jobs - 1)
        if not self._closing:
            self._pump_icon_gallery_jobs()

    def show_icon_gallery(
        self,
        item: UpdateItem,
        *,
        parent: Any,
        reuse_window: Any | None = None,
        navigation_direction: int = 0,
    ) -> None:
        """Open or retarget a lineup of locally available icon representations."""

        tk, ttk = self.tk, self.ttk
        px = self.visuals.px
        snapshot = dataclasses.replace(item)
        if reuse_window is None:
            existing = self._icon_lineup_windows.get(snapshot.key)
            try:
                if existing is not None and existing.winfo_exists():
                    if existing.state() == "iconic":
                        existing.deiconify()
                    existing.lift()
                    existing.focus_set()
                    return
            except tk.TclError:
                pass
            self._icon_lineup_windows.pop(snapshot.key, None)
        window = reuse_window
        try:
            reuse_existing = bool(window is not None and window.winfo_exists())
        except tk.TclError:
            reuse_existing = False
        if reuse_existing:
            cleanup = getattr(window, "_icon_lineup_cleanup", None)
            if callable(cleanup):
                with contextlib.suppress(Exception):
                    cleanup()
            for child in window.winfo_children():
                with contextlib.suppress(tk.TclError):
                    child.destroy()
            self._refresh_registered_theme_widgets()
        else:
            window = self._create_toplevel(self.root)
            window.geometry(self.visuals.geometry_from_dips("760x380"))
            window.minsize(px(640), px(330))
        self._icon_lineup_windows[snapshot.key] = window
        lineup_token = object()
        window._icon_lineup_token = lineup_token
        window.title(f"Icon lineup - {snapshot.name}")
        frame = ttk.Frame(window, padding=px(16))
        frame.pack(fill="both", expand=True)
        ttk.Label(
            frame,
            text=f"Icon lineup — {snapshot.name}",
            font=self._ui_font(15, semibold=True, display=True),
        ).pack(anchor="w")
        ttk.Label(
            frame,
            text="Local icon representations, ordered from smallest to largest.",
            style="Subtitle.TLabel",
        ).pack(anchor="w", pady=(px(2), px(10)))
        status = ttk.Label(frame, text="Finding local icon representations…")
        status.pack(anchor="w", pady=(0, px(8)))

        gallery_frame = ttk.Frame(frame)
        gallery_frame.pack(fill="both", expand=True)
        canvas = tk.Canvas(gallery_frame, bd=0, highlightthickness=0)
        self._register_theme_widget(canvas, background="window")
        xscroll = ttk.Scrollbar(gallery_frame, orient="horizontal", command=canvas.xview)
        yscroll = ttk.Scrollbar(gallery_frame, orient="vertical", command=canvas.yview)
        canvas.configure(xscrollcommand=xscroll.set, yscrollcommand=yscroll.set)
        canvas.grid(row=0, column=0, sticky="nsew")
        yscroll.grid(row=0, column=1, sticky="ns")
        xscroll.grid(row=1, column=0, sticky="ew")
        gallery_frame.columnconfigure(0, weight=1)
        gallery_frame.rowconfigure(0, weight=1)
        inner = ttk.Frame(canvas, padding=(px(8), px(8)))
        # Assemble the complete lineup off-paint. Attaching a growing row of
        # image canvases to a mapped Tk window can expose their uninitialized
        # native backing surfaces as brief black rectangles. The user should
        # see only the stable themed canvas until artwork, captions, geometry,
        # and scroll bounds are all ready for one atomic reveal.
        inner_id = canvas.create_window(
            (0, 0),
            window=inner,
            anchor="nw",
            state="hidden",
        )
        images: list[Any] = []
        # Tk does not retain PhotoImage objects referenced only by a completed
        # callback. Keep them on the window for exactly as long as the lineup
        # is open, otherwise the captions survive while the artwork vanishes.
        window._icon_lineup_images = images
        checker_canvases: list[Any] = []
        checker_after_id: str | None = None
        neighbor_prefetch_after_id: str | None = None
        deep_prefetch_after_id: str | None = None
        checker_phase = 0.0
        checker_step = 0.5
        checker_interval_ms = 90
        checker_tile = max(10, px(10))
        checker_period = checker_tile * 2

        def animate_checkerboards() -> None:
            nonlocal checker_after_id, checker_phase
            try:
                if not window.winfo_exists():
                    return
                for checker_canvas in checker_canvases:
                    checker_canvas.move("checkerboard", checker_step, checker_step)
                checker_phase += checker_step
                if checker_phase >= checker_period:
                    for checker_canvas in checker_canvases:
                        checker_canvas.move(
                            "checkerboard", -checker_period, -checker_period
                        )
                    checker_phase = 0
                checker_after_id = window.after(
                    checker_interval_ms, animate_checkerboards
                )
            except tk.TclError:
                checker_after_id = None

        def stop_checkerboards(event: Any) -> None:
            if event.widget is window:
                cleanup_lineup()

        def cleanup_lineup() -> None:
            nonlocal checker_after_id, neighbor_prefetch_after_id, deep_prefetch_after_id
            if self._icon_lineup_windows.get(snapshot.key) is window:
                self._icon_lineup_windows.pop(snapshot.key, None)
            active_showcase = getattr(window, "_icon_lineup_showcase", None)
            if active_showcase is not None:
                with contextlib.suppress(tk.TclError):
                    active_showcase.destroy()
                window._icon_lineup_showcase = None
            for after_id in (
                checker_after_id,
                neighbor_prefetch_after_id,
                deep_prefetch_after_id,
            ):
                if after_id is not None:
                    with contextlib.suppress(tk.TclError):
                        window.after_cancel(after_id)
            checker_after_id = None
            neighbor_prefetch_after_id = None
            deep_prefetch_after_id = None
            checker_canvases.clear()
            images.clear()

        window._icon_lineup_cleanup = cleanup_lineup
        window.bind("<Destroy>", stop_checkerboards)

        def update_scrollregion(_event: Any = None) -> None:
            with contextlib.suppress(tk.TclError):
                canvas.configure(scrollregion=canvas.bbox("all"))

        inner.bind("<Configure>", update_scrollregion, add="+")
        canvas.bind(
            "<MouseWheel>",
            lambda event: canvas.xview_scroll(-1 if event.delta > 0 else 1, "units"),
            add="+",
        )

        def save_lineup_representation(
            png_data: bytes, filename: str, width: int, height: int
        ) -> None:
            safe_name = (
                re.sub(r"[^A-Za-z0-9 _.-]+", "-", snapshot.name).strip(" .-")
                or "package-icon"
            )
            destination_text = self.filedialog.asksaveasfilename(
                parent=window,
                title=f"Save {width} × {height} icon for {snapshot.name}",
                defaultextension=".png",
                initialfile=f"{safe_name}-{width}x{height}.png",
                filetypes=(("PNG image", "*.png"), ("All files", "*.*")),
            )
            if not destination_text:
                return
            destination = Path(destination_text)
            try:
                destination.write_bytes(png_data)
                self.summary_var.set(f"Saved lineup icon for {snapshot.name}")
                self._append_log(
                    f"Saved lineup icon for {snapshot.name}: {destination}",
                    show_in_ui=False,
                )
                self.logger.event(
                    "icon_lineup_representation_saved",
                    item=item_diagnostic_fields(snapshot),
                    width=width,
                    height=height,
                    destination_path=str(destination),
                )
            except OSError as exc:
                self._notify_user(
                    f"Could not save this lineup icon: {exc}",
                    level="error",
                    summary="Could not save lineup icon",
                )

        def bind_lineup_save(
            widget: Any,
            png_data: bytes,
            filename: str,
            width: int,
            height: int,
        ) -> None:
            def show_menu(event: Any) -> str:
                menu = self._new_context_menu(widget)
                menu.add_command(
                    label="Save this PNG as…",
                    command=lambda: save_lineup_representation(
                        png_data, filename, width, height
                    ),
                )
                try:
                    menu.tk_popup(int(event.x_root), int(event.y_root))
                finally:
                    menu.grab_release()
                return "break"

            widget.bind("<Button-3>", show_menu, add="+")
            widget.bind(
                "<Double-Button-1>",
                lambda event: self.show_icon_showcase(
                    png_data,
                    filename,
                    width,
                    height,
                    parent=window,
                    package_name=snapshot.name,
                    backdrop=icon_showcase_background(event.state),
                ),
                add="+",
            )
            self._bind_widget_tooltip(
                widget,
                f"Double-click for a nearest-neighbor 3× showcase on white; "
                f"hold Shift for black or Ctrl for checkerboard. "
                f"Double-click it to close. "
                f"Right-click to save this {width} × {height} PNG.",
            )

        def present(bundle: IconGalleryMemoryBundle, error: str) -> None:
            nonlocal checker_after_id, neighbor_prefetch_after_id, deep_prefetch_after_id
            if getattr(window, "_icon_lineup_token", None) is not lineup_token:
                return
            try:
                if not window.winfo_exists():
                    return
            except tk.TclError:
                return

            def prefetch_neighbors() -> None:
                nonlocal neighbor_prefetch_after_id
                neighbor_prefetch_after_id = None
                if getattr(window, "_icon_lineup_token", None) is not lineup_token:
                    return
                rows = [str(row) for row in self.tree.get_children() if str(row) in self.items]
                if snapshot.key not in rows:
                    return
                index = rows.index(snapshot.key)
                forward = 1 if navigation_direction >= 0 else -1
                offsets = [forward * distance for distance in range(1, 7)]
                offsets.extend(-forward * distance for distance in range(1, 4))
                for offset in offsets:
                    neighbor_index = index + offset
                    if 0 <= neighbor_index < len(rows):
                        neighbor = self.items.get(rows[neighbor_index])
                        if neighbor is not None:
                            self._prepare_icon_gallery_session(neighbor)

            neighbor_prefetch_after_id = window.after(250, prefetch_neighbors)

            def prefetch_remaining_inventory() -> None:
                nonlocal deep_prefetch_after_id
                deep_prefetch_after_id = None
                if getattr(window, "_icon_lineup_token", None) is not lineup_token:
                    return
                rows = [str(row) for row in self.tree.get_children() if str(row) in self.items]
                if snapshot.key not in rows:
                    return
                available_memory = available_physical_memory_bytes()
                capacity = icon_gallery_prefetch_capacity(
                    len(rows),
                    available_memory=available_memory,
                )
                remaining_capacity = max(
                    0,
                    capacity
                    - len(self._icon_gallery_preparations)
                    - len(self._icon_gallery_inflight),
                )
                if remaining_capacity <= 0:
                    return
                index = rows.index(snapshot.key)
                forward = 1 if navigation_direction >= 0 else -1
                scheduled = 0
                for distance in range(7, len(rows) + 1):
                    for offset in (forward * distance, -forward * distance):
                        neighbor_index = index + offset
                        if not 0 <= neighbor_index < len(rows):
                            continue
                        neighbor = self.items.get(rows[neighbor_index])
                        if neighbor is None:
                            continue
                        if (
                            neighbor.key in self._icon_gallery_preparations
                            or neighbor.key in self._icon_gallery_inflight
                        ):
                            continue
                        self._prepare_icon_gallery_session(neighbor)
                        scheduled += 1
                        if scheduled >= remaining_capacity:
                            break
                    if scheduled >= remaining_capacity:
                        break
                if scheduled:
                    self.logger.event(
                        "icon_gallery_idle_prefetch_scheduled",
                        anchor_item_key=snapshot.key,
                        scheduled=scheduled,
                        capacity=capacity,
                        available_memory_bytes=available_memory,
                        worker_limit=2,
                    )

            # A deliberate pause means exploration has settled. Fill the
            # two-lane low-priority queue outward through the remaining list;
            # any visible Ctrl+arrow request is promoted ahead of this work.
            deep_prefetch_after_id = window.after(1400, prefetch_remaining_inventory)
            if error and not bundle.item_count:
                status.configure(text=f"The icon lineup could not be completed: {error}")
                return
            try:
                prepared = self._icon_gallery_preparations.get(snapshot.key, {})
                cached_items = prepared.get("items")
                items = list(cached_items) if isinstance(cached_items, tuple) else bundle.unpack()
            except (KeyError, TypeError, UnicodeDecodeError, ValueError) as exc:
                status.configure(text="The in-memory icon lineup could not be decoded.")
                self.logger.event(
                    "icon_gallery_memory_decode_failed",
                    item=item_diagnostic_fields(snapshot),
                    cache_format="raw-memory",
                    error=f"{type(exc).__name__}: {exc}",
                )
                return
            items = self._displayable_icon_gallery_items(snapshot, items)
            if not items:
                status.configure(text="No additional local icon representations were found.")
                return
            generic_only = all(
                record.get("generic_shell_fallback") for record, _png_data in items
            )
            status.configure(
                text=(
                    "Only Windows' generic executable artwork was available locally."
                    if generic_only
                    else f"Found {len(items)} icon representation(s)."
                    + (" Some original artwork could not be read." if error else "")
                )
            )
            monitor_window = window if reuse_existing else parent
            try:
                work_left, work_top, work_right, work_bottom = window_monitor_work_area(
                    monitor_window
                )
            except tk.TclError:
                work_left, work_top, work_right, work_bottom = window_monitor_work_area(window)
            work_width = max(px(640), work_right - work_left)
            work_height = max(px(480), work_bottom - work_top)
            maximum_art = max(px(96), min(px(256), work_height - px(300)))
            column = 0
            content_width = px(28)
            tallest = 0
            for index, (record, png_data) in enumerate(items):
                try:
                    filename = str(record.get("filename", f"icon-{index + 1}.png"))
                    width = int(record["width"])
                    height = int(record["height"])
                    digest = hashlib.sha256(png_data).digest()
                    image = self._cached_icon_gallery_image(
                        (digest, 1),
                        lambda: tk.PhotoImage(data=png_data, format="png"),
                    )
                except (KeyError, ValueError, tk.TclError):
                    continue
                subsample = max(1, math.ceil(max(width, height) / maximum_art))
                displayed = (
                    self._cached_icon_gallery_image(
                        (digest, subsample),
                        lambda: image.subsample(subsample, subsample),
                    )
                    if subsample > 1
                    else image
                )
                images.extend((image, displayed) if displayed is not image else (image,))
                card_width = max(px(132), displayed.width() + px(20))
                card = ttk.Frame(inner, padding=(px(8), px(6)))
                card.grid(row=0, column=column, sticky="ns", padx=(0, px(6)))
                if bool(record.get("checkerboard")):
                    artwork = tk.Canvas(
                        card,
                        width=displayed.width(),
                        height=displayed.height(),
                        bd=0,
                        highlightthickness=0,
                    )
                    self._register_theme_widget(artwork, background="window")
                    for checker_y, y in enumerate(
                        range(-checker_period, displayed.height() + checker_period, checker_tile)
                    ):
                        for checker_x, x in enumerate(
                            range(
                                -checker_period,
                                displayed.width() + checker_period,
                                checker_tile,
                            )
                        ):
                            color = (
                                "#f2f2f2"
                                if (checker_x + checker_y) % 2 == 0
                                else "#b9b9b9"
                            )
                            artwork.create_rectangle(
                                x,
                                y,
                                x + checker_tile,
                                y + checker_tile,
                                fill=color,
                                outline=color,
                                tags=("checkerboard",),
                            )
                    artwork.create_image(
                        displayed.width() // 2,
                        displayed.height() // 2,
                        image=displayed,
                        anchor="center",
                    )
                    artwork.pack(anchor="center", pady=(0, px(6)))
                    checker_canvases.append(artwork)
                else:
                    artwork = ttk.Label(card, image=displayed)
                    artwork.pack(anchor="center", pady=(0, px(6)))
                bind_lineup_save(artwork, png_data, filename, width, height)
                size_text = f"{width} × {height} px"
                if subsample > 1:
                    size_text += f"\n(displayed at 1/{subsample} scale)"
                represented_sizes = {
                    (int(value[0]), int(value[1]))
                    for value in record.get("represented_sizes", [])
                    if isinstance(value, list) and len(value) == 2
                }
                if len(represented_sizes) > 1:
                    extents = sorted(max(value) for value in represented_sizes)
                    size_text += (
                        f"\nrepresents {len(represented_sizes)} matching sizes "
                        f"({extents[0]}–{extents[-1]} px)"
                    )
                ttk.Label(
                    card,
                    text=size_text,
                    font=self._ui_font(9, semibold=True),
                    justify="center",
                ).pack(anchor="center")
                source_names = [Path(str(value)).name for value in record.get("sources", [])]
                source_text = ", ".join(source_names[:3]) or "Local artwork"
                if record.get("generated_vector"):
                    source_text = "Generated vector bitmap"
                if len(source_names) > 3:
                    source_text += f" + {len(source_names) - 3} more files"
                ttk.Label(
                    card,
                    text=source_text,
                    justify="center",
                    wraplength=card_width,
                ).pack(anchor="center", pady=(px(3), 0))
                retrievals = [str(value) for value in record.get("retrievals", [])]
                retrieval_text = "\n".join(retrievals[:3])
                if len(retrievals) > 3:
                    retrieval_text += f"\n+ {len(retrievals) - 3} equivalent retrievals"
                ttk.Label(
                    card,
                    text=retrieval_text,
                    style="Subtitle.TLabel",
                    justify="center",
                    wraplength=card_width,
                ).pack(anchor="center", pady=(px(3), 0))
                content_width += card_width + px(6)
                tallest = max(tallest, displayed.height() + px(145))
                column += 1
            if not images:
                status.configure(text="The retrieved icon files could not be displayed.")
                return
            window.update_idletasks()
            # Captions and long native filenames can make a card wider than
            # the artwork-based estimate. Trust Tk's completed layout so the
            # rightmost, usually best representation is not clipped by our own
            # window sizing calculation.
            measured_content_width = max(content_width, int(inner.winfo_reqwidth()))
            window_overhead = px(16 * 2 + 18) + int(yscroll.winfo_reqwidth())
            margin_x = max(px(12), int(work_width * 0.012))
            margin_y = max(px(12), int(work_height * 0.025))
            maximum_width = max(px(640), work_width - margin_x * 2)
            maximum_height = max(px(330), work_height - margin_y * 2)
            desired_width = min(
                maximum_width,
                max(px(760), measured_content_width + window_overhead),
            )
            if reuse_existing:
                desired_width = min(maximum_width, max(desired_width, window.winfo_width()))
            desired_height = min(maximum_height, max(px(350), tallest + px(125)))
            x = work_left + max(margin_x, (work_width - desired_width) // 2)
            y = work_top + max(margin_y, (work_height - desired_height) // 2)
            window.geometry(f"{desired_width}x{desired_height}{x:+d}{y:+d}")
            window.update_idletasks()
            canvas.itemconfigure(inner_id, height=max(tallest, canvas.winfo_height()))
            canvas.itemconfigure(inner_id, state="normal")
            update_scrollregion()
            if measured_content_width > canvas.winfo_width():
                # The lineup is intentionally smallest-to-largest. If even a
                # near-full-monitor window cannot contain everything, reveal
                # the most useful largest artwork first; the scrollbar remains
                # available for the smaller historical representations.
                canvas.xview_moveto(1.0)
            else:
                canvas.xview_moveto(0.0)
            if (
                checker_canvases
                and checker_after_id is None
                and system_client_animations_enabled()
            ):
                checker_after_id = window.after(
                    checker_interval_ms, animate_checkerboards
                )

        def cycle_lineup(direction: int) -> str:
            rows = [str(row) for row in self.tree.get_children() if str(row) in self.items]
            if snapshot.key not in rows:
                return "break"
            next_index = rows.index(snapshot.key) + direction
            if not 0 <= next_index < len(rows):
                return "break"
            next_item = self.items.get(rows[next_index])
            if next_item is None:
                return "break"
            with contextlib.suppress(tk.TclError):
                self.tree.selection_set(next_item.key)
                self.tree.focus(next_item.key)
                self.tree.see(next_item.key)
            self.show_icon_gallery(
                next_item,
                parent=parent,
                reuse_window=window,
                navigation_direction=direction,
            )
            return "break"

        # Match Package Details' natural arrow-key navigation. Retain the
        # original Ctrl+Arrow developer shortcut as an alias so either muscle
        # memory keeps the same lineup window racing through the package list.
        for sequence, direction in (
            ("<Left>", -1),
            ("<Right>", 1),
            ("<Control-Left>", -1),
            ("<Control-Right>", 1),
        ):
            window.bind(
                sequence,
                lambda _event, step=direction: cycle_lineup(step),
            )
        window.lift()
        window.focus_set()
        self._prepare_icon_gallery_session(snapshot, present)

    def _finish_icon_showcase_request(
        self, cache_key: str, callbacks: list[Callable[..., None]],
        rendered_png: bytes, mode: str, analysis: Mapping[str, Any], error: str,
    ) -> None:
        # A cache clear supersedes the request without allowing its late result
        # to repopulate caches or consume callbacks for a newer same-key request.
        if self._closing or self._icon_showcase_inflight.get(cache_key) is not callbacks:
            return
        del self._icon_showcase_inflight[cache_key]
        if rendered_png and not error:
            self._icon_showcase_cache[cache_key] = (rendered_png, mode, dict(analysis))
            self._icon_showcase_cache.move_to_end(cache_key)
            while len(self._icon_showcase_cache) > 16:
                self._icon_showcase_cache.popitem(last=False)
        for callback in callbacks:
            with contextlib.suppress(self.tk.TclError):
                callback(rendered_png, mode, analysis, error)

    def show_icon_showcase(
        self,
        png_data: bytes,
        filename: str,
        width: int,
        height: int,
        *,
        parent: Any,
        package_name: str,
        backdrop: str = "white",
    ) -> str:
        """Display the supplied pixels once using native integer nearest-neighbor scaling."""

        if not png_data or width <= 0 or height <= 0:
            return "break"
        tk = self.tk
        px = self.visuals.px
        previous_showcase = getattr(parent, "_icon_lineup_showcase", None)
        if previous_showcase is not None:
            with contextlib.suppress(tk.TclError):
                previous_showcase.destroy()
        try:
            work_left, work_top, work_right, work_bottom = window_monitor_work_area(parent)
        except tk.TclError:
            return "break"
        work_width = max(1, work_right - work_left)
        work_height = max(1, work_bottom - work_top)
        maximum_side = max(
            px(96),
            min(
                MAX_ICON_SHOWCASE_SIZE,
                int(work_width * 0.88),
                int(work_height * 0.88),
            ),
        )
        available_side = max(1, maximum_side - 8)
        zoom_factor = max(1, min(3, available_side // max(width, height)))
        subsample_factor = max(1, math.ceil(max(width, height) / available_side))
        art_target_width = max(1, math.ceil(width / subsample_factor) * zoom_factor)
        art_target_height = max(1, math.ceil(height / subsample_factor) * zoom_factor)
        target_width, target_height = art_target_width + 8, art_target_height + 8
        side = max(px(96), target_width, target_height)
        side = min(side, maximum_side)

        source_image = None
        decode_error = ""
        requested_backdrop = backdrop
        try:
            source_image = tk.PhotoImage(data=png_data, format="png")
            backdrop = icon_showcase_contrast_backdrop(source_image, backdrop)
        except tk.TclError as exc:
            decode_error = f"{type(exc).__name__}: {exc}"
        background = {"black": "#000000", "gray": "#808080"}.get(backdrop, "#ffffff")
        showcase = self._create_toplevel(parent, background=background)
        parent._icon_lineup_showcase = showcase
        showcase.transient(parent)
        showcase.title(f"Icon showcase - {package_name}")
        showcase.resizable(False, False)
        foreground = "#d8d8d8" if background == "#000000" else "#303030"
        canvas = tk.Canvas(
            showcase,
            width=side,
            height=side,
            bd=0,
            highlightthickness=1,
            highlightbackground=self.palette["border"],
            background=background,
        )
        canvas.pack(fill="both", expand=True)
        if backdrop == "checkerboard":
            # One static, tiled image stays behind the artwork.
            tile = tk.PhotoImage(width=2, height=2)
            tile.put((("#ffffff", "#b8b8b8"), ("#b8b8b8", "#ffffff")))
            tile = tile.zoom(max(1, px(8)))
            checker = tk.PhotoImage(width=side, height=side)
            tk_image = canvas.tk
            tk_image.call(str(checker), "copy", str(tile), "-to", 0, 0, side, side)
            showcase._showcase_checker = checker
            canvas.create_image(0, 0, image=checker, anchor="nw", tags="backdrop")
        parent.update_idletasks()
        x = parent.winfo_rootx() + (parent.winfo_width() - side) // 2
        y = parent.winfo_rooty() + (parent.winfo_height() - side) // 2
        x = min(max(work_left, x), max(work_left, work_right - side))
        y = min(max(work_top, y), max(work_top, work_bottom - side))
        showcase.geometry(f"{side}x{side}{x:+d}{y:+d}")
        showcase.bind("<Double-Button-1>", lambda _event: showcase.destroy(), add="+")

        def clear_showcase_reference(event: Any) -> None:
            if event.widget is showcase and getattr(parent, "_icon_lineup_showcase", None) is showcase:
                parent._icon_lineup_showcase = None

        showcase.bind("<Destroy>", clear_showcase_reference, add="+")

        focus_guard_armed = False

        def arm_focus_guard() -> None:
            nonlocal focus_guard_armed
            focus_guard_armed = True

        def dismiss_if_focus_left(_event: Any = None) -> None:
            if not focus_guard_armed:
                return

            def check() -> None:
                try:
                    focused = showcase.focus_displayof()
                    if focused is None or not str(focused).startswith(str(showcase)):
                        showcase.destroy()
                except tk.TclError:
                    pass

            showcase.after_idle(check)

        showcase.bind("<FocusOut>", dismiss_if_focus_left, add="+")
        showcase.after(180, arm_focus_guard)

        # The Lineup already supplied a displayable PNG. Native pixel replication
        # is the sole render: no helper launch, loading state or later replacement.
        try:
            if source_image is None:
                raise tk.TclError(decode_error)
            image = source_image.subsample(subsample_factor) if subsample_factor > 1 else source_image
            if zoom_factor > 1:
                image = image.zoom(zoom_factor)
            showcase._showcase_image = image
            canvas.create_image(side // 2, side // 2, image=image, anchor="center", tags="artwork")
            self.logger.event(
                "icon_showcase_presented", package_name=package_name, source=filename,
                source_size=[width, height], rendered_size=[art_target_width, art_target_height],
                artwork_size=[art_target_width, art_target_height],
                scaling_mode="tk-integer-nearest", backdrop=backdrop,
                requested_backdrop=requested_backdrop,
                analysis={"white_on_white_outline": False},
            )
        except tk.TclError as exc:
            canvas.create_text(
                side // 2, side // 2, text="Showcase unavailable",
                fill=foreground, font=self._ui_font(10, semibold=True), tags="artwork",
            )
            self.logger.event(
                "icon_showcase_failed", package_name=package_name, source=filename,
                error=f"{type(exc).__name__}: {exc}",
            )
        return "break"

    def _copy_text(
        self, value: str, *, log_message: str = "Copied guided text to clipboard"
    ) -> None:
        if not self._set_clipboard(value):
            return
        self.summary_var.set(log_message)
        self._append_log(log_message, show_in_ui=False)

    def save_system_report(self) -> None:
        if self.busy or self._scan_active:
            return
        inventory = list(self._scan_view_items[True].values())
        if not inventory:
            self._notify_user(
                "No installed-app inventory is available yet. Run Scan first.",
                level="warning",
                summary="Scan before saving a system report",
            )
            return
        destination_text = self.filedialog.asksaveasfilename(
            parent=self.root,
            title="Save WinDevPilot system report",
            defaultextension=".txt",
            initialfile=(
                f"{APP_NAME}-system-report-{dt.datetime.now():%Y%m%d-%H%M%S}.txt"
            ),
            filetypes=(("Text report", "*.txt"), ("All files", "*.*")),
            confirmoverwrite=True,
        )
        if not destination_text:
            return
        inventory.sort(
            key=lambda item: (
                item.name.casefold(),
                self._provider_display_label(item).casefold(),
                item.package_id.casefold(),
                item.key,
            )
        )
        update_items = list(self._scan_view_items[False].values())
        rows: list[tuple[str, ...]] = []
        for item in inventory:
            displayed = self._item_row_values(item)
            date = self._installed_service_date_evidence(item)
            update_version = (
                ""
                if self._item_inventory_is_provisional(item)
                else system_report_update_version(item, update_items)
            )
            # The table compacts long portable IDs with an ellipsis; a saved
            # system inventory must retain the full underlying package identity.
            rows.append(
                (
                    displayed[1],
                    item.package_id,
                    displayed[3],
                    date.report_text,
                    displayed[6],
                    self._run_as_label(item),
                    f"Update available — {update_version}" if update_version else "",
                    system_report_path_text(item.installed_location),
                    item.installed_technology,
                    human_size_from_kb(item.installed_size_kb),
                )
            )
        provisional_count = sum(
            self._item_inventory_is_provisional(item) for item in inventory
        )
        try:
            report_path = write_system_report(
                Path(destination_text),
                rows,
                provisional_count=provisional_count,
            )
            report_size = report_path.stat().st_size
        except (OSError, ValueError) as exc:
            error = f"{type(exc).__name__}: {exc}"
            self.logger.event(
                "system_report_save_failed",
                destination_path=destination_text,
                error=error,
            )
            self._notify_user(
                f"The system report could not be saved: {error}",
                level="error",
                summary="System report could not be saved",
            )
            return
        self.logger.event(
            "system_report_saved",
            destination_path=str(report_path),
            item_count=len(rows),
            provisional_item_count=provisional_count,
            size_bytes=report_size,
            maximum_size_bytes=SYSTEM_REPORT_MAX_BYTES,
        )
        self._notify_user(
            f"System report saved: {report_path}",
            level="success",
            summary=f"System report saved ({len(rows)} installed apps)",
        )

    def create_diagnostic_bundle_from_ui(self) -> None:
        if self._diagnostic_bundle_inflight:
            return
        self._diagnostic_bundle_inflight = True
        if self.bundle_button is not None:
            self.bundle_button.configure(state="disabled")
        self.summary_var.set("Building diagnostic bundle in the background…")
        self._append_log("Building diagnostic bundle…", show_in_ui=False)
        settings_snapshot = json.loads(json.dumps(self.settings.data))
        item_snapshots = [dataclasses.replace(item) for item in self.items.values()]

        def worker() -> None:
            bundle_path = create_diagnostic_bundle(
                self.logger,
                settings_snapshot,
                item_snapshots,
            )
            self.events.put(("diagnostic_bundle_done", str(bundle_path)))

        self._start_guarded_worker(
            worker,
            name="wdp-diagnostic-bundle",
            operation="diagnostic-bundle",
        )

    def _finish_diagnostic_bundle(self, bundle_path_text: str) -> None:
        self._diagnostic_bundle_inflight = False
        if self.bundle_button is not None:
            self.bundle_button.configure(state="disabled" if self.busy else "normal")
        bundle_path = Path(bundle_path_text)
        self.logger.event(
            "diagnostic_bundle_created",
            path=str(bundle_path),
            size_bytes=bundle_path.stat().st_size,
            maximum_size_bytes=DIAGNOSTIC_BUNDLE_MAX_BYTES,
            visible_item_count=len(self.items),
        )
        if self._set_clipboard(str(bundle_path)):
            self._notify_user(
                f"Diagnostic bundle created and copied to the clipboard: {bundle_path}",
                level="success",
                summary="Diagnostic bundle path copied to clipboard",
            )
        else:
            self._append_log(f"Diagnostic bundle created: {bundle_path}")

    def item_details_text(
        self,
        item: UpdateItem,
        *,
        icon_evidence: Mapping[str, Any] | None = None,
    ) -> str:
        provisional = self._item_inventory_is_provisional(item)
        steam_inventory = is_steam_arp_inventory_item(item)
        provider_label = self._provider_display_label(item)
        source_label = (
            "Steam uninstall registration"
            if steam_inventory
            else item.source or "(default)"
        )
        hold_record = self.settings.data.get("attempt_holds", {}).get(item.candidate_key, {})
        if not isinstance(hold_record, dict):
            hold_record = {}
        product_codes = ", ".join(item.product_codes) if item.product_codes else "(none)"
        metadata_sources = ", ".join(item.metadata_sources) if item.metadata_sources else "(none)"
        installed_size = human_size_from_kb(item.installed_size_kb) or "(not available)"
        date = self._installed_service_date_evidence(item)
        installed_date = date.detail_text or "(not available)"
        installed_version = (
            f"Checking… (previously {item.current})" if provisional else item.current
        )
        if verified_version := self._early_verified_installed_version(item):
            installed_version = f"{verified_version} (verified after this install)"
        available_version = (
            f"Checking… (previously {item.available})" if provisional else item.available
        )
        package_history = package_history_for_item(self.settings.data, item)
        installation_observation = getattr(self, "_installation_observations", {}).get(
            update_observation_identity_key(item), {}
        )
        release_observation = getattr(self, "_update_release_observations", {}).get(
            update_observation_identity_key(item), {}
        )
        if not (
            isinstance(release_observation, Mapping)
            and update_versions_equivalent(
                str(release_observation.get("available_version", "")),
                item.available,
            )
        ):
            release_observation = {}
        lines = [
            "Package",
            f"  Name: {item.name}",
            f"  ID: {item.package_id}",
            f"  Provider: {provider_label}",
            f"  Source: {source_label}",
            "",
            "Versions",
            f"  Installed: {installed_version}",
            f"  Available: {available_version}",
            "",
            "Identity and execution",
            f"  WinDevPilot scope: {item.scope}",
            f"  Installed for: {item.installed_for or '(not proven)'}",
            f"  Installed technology: {item.installed_technology or '(not proven)'}",
            f"  Installed location: {item.installed_location or '(not available)'}",
            f"  Installed size: {installed_size}",
            f"  Installed / last serviced: {installed_date}",
            f"  Product codes: {product_codes}",
            f"  Available technology: {item.available_technology or '(not probed)'}",
            f"  Available scope: {item.available_scope or '(not probed)'}",
            f"  Upgrade behavior: {item.available_upgrade_behavior or '(not probed)'}",
            f"  Will run as: {self._run_as_label(item)}",
            f"  Requires admin: {item.requires_admin}",
        ]
        action_summary = [f"  Status: {item.status}"]
        if item.guidance:
            action_summary.append(f"  Guidance: {item.guidance}")
        lines[5:5] = action_summary
        if steam_inventory:
            lines.insert(5, "  Discovered through: WinGet installed inventory")
        if provisional:
            lines[5:5] = [
                "",
                "Freshness",
                "  Previous inventory — this provider has not finished refreshing",
                "  Package-changing actions remain disabled until the row is current",
            ]
        package_metadata = []
        if item.publisher:
            package_metadata.append(f"  Publisher: {item.publisher}")
        if item.architecture:
            package_metadata.append(f"  Architecture: {item.architecture}")
        if item.description:
            package_metadata.append(f"  Description: {item.description}")
        lines[5:5] = package_metadata
        if date.date:
            evidence_index = lines.index(f"  Product codes: {product_codes}")
            evidence_lines = [
                f"  Date/time evidence: {date.source or '(source not recorded)'}"
            ]
            if date.timestamp_precision:
                evidence_lines.append(
                    "  Recorded precision: "
                    + wall_clock_precision_label(date.timestamp_precision)
                )
            lines[evidence_index:evidence_index] = evidence_lines
        if item.installed_registration_changed_at:
            registration_index = lines.index(f"  Product codes: {product_codes}")
            registration_lines = [
                "  Installed-app registration last changed: "
                + local_observation_time(
                    item.installed_registration_changed_at,
                    item.installed_registration_changed_at_precision,
                ),
                "  Registration-time meaning: approximate service/registration clue; "
                "not proof of the original installation time",
            ]
            lines[registration_index:registration_index] = registration_lines
        if (date.history_action or date.observation_kind) and item.installed_date:
            native_date = installed_service_date_evidence(item, {})
            if native_date.date:
                index = lines.index(f"  Product codes: {product_codes}")
                lines[index:index] = [
                    f"  Windows/provider date/time: {native_date.detail_text}",
                    f"  Windows/provider date/time evidence: {native_date.source or '(source not recorded)'}",
                ]
        if package_history:
            history_lines = ["", "WinDevPilot history"]
            installed_at = package_history.get("installed_at", "")
            serviced_at = package_history.get("serviced_at", "")
            if installed_at:
                version = package_history.get("installed_version", "")
                history_lines.append(
                    (
                        "  Installed through WinDevPilot: "
                        if package_history.get("installed_exact") and package_history.get("installed_current")
                        else "  WinDevPilot recorded installing this package ID: "
                    )
                    + f"{local_observation_time(installed_at)}"
                    + (f" (version {version})" if version else "")
                )
                try:
                    remembered_date = dt.datetime.fromisoformat(installed_at)
                    if remembered_date.tzinfo is None:
                        remembered_date = remembered_date.astimezone()
                    if (
                        item.installed_date
                        and not item.installed_date_is_estimate
                        and dt.date.fromisoformat(item.installed_date)
                        > remembered_date.astimezone().date() + dt.timedelta(days=1)
                    ):
                        history_lines.append(
                            "  Current Windows registration is dated later; it may have "
                            "been serviced or reinstalled since that action"
                        )
                except (TypeError, ValueError):
                    pass
            if serviced_at and (
                not installed_at
                or serviced_at != installed_at
                or package_history.get("last_action") != "install"
            ):
                version = package_history.get("serviced_version", "")
                action_label = "installed" if package_history.get("last_action") == "install" else "updated"
                history_lines.append(
                    (
                        f"  Last {action_label} by WinDevPilot: "
                        if package_history.get("serviced_current")
                        else f"  WinDevPilot previously {action_label} this package ID: "
                    )
                    + f"{local_observation_time(serviced_at)}"
                    + (f" (target {version})" if version else "")
                )
            if (installed_at and not package_history.get("installed_current")) or (
                serviced_at and not package_history.get("serviced_current")
            ):
                history_lines.append(
                    "  Earlier actions are historical only and do not date the current "
                    "installation: inventory continuity since those actions is unconfirmed"
                )
            history_lines.append(
                "  Evidence: remembered successful WinDevPilot action; retained until app data is cleared"
            )
            lines.extend(history_lines)
        if date.observation_kind and isinstance(installation_observation, Mapping):
            previous_version = str(installation_observation.get("previous_version", ""))
            observation_label = (
                "Installation/registration first appeared"
                if date.observation_kind == "installed-or-reappeared"
                else f"Installed version changed{f' from {previous_version}' if previous_version else ''}"
            )
            lines.extend(
                [
                    "",
                    "Installed-version observation",
                    f"  {observation_label}: after {local_observation_time(date.window_start)}",
                    f"  Current version {item.current} first observed: "
                    f"{local_observation_time(date.window_end)}",
                    f"  Observed service window: after {local_observation_time(date.window_start)} "
                    f"and by {local_observation_time(date.window_end)}",
                    "  Meaning: inferred from complete provider inventories; this may be an "
                    "external install, update, repair, or registration change—not necessarily "
                    "the application's original installation",
                ]
            )
        if release_observation:
            first_seen = str(release_observation.get("first_seen_at", ""))
            last_absent = str(release_observation.get("last_absent_at", ""))
            lines.extend(["", "Update availability observation"])
            lines.append(
                f"  Version {item.available} first observed offered: "
                f"{local_observation_time(first_seen)}"
            )
            if last_absent:
                lines.extend(
                    [
                        "  Last complete scan without this version: "
                        f"{local_observation_time(last_absent)}",
                        "  Observed release window: after "
                        f"{local_observation_time(last_absent)} and by "
                        f"{local_observation_time(first_seen)}",
                    ]
                )
            else:
                lines.append(
                    "  Earlier no-offer boundary: not recorded in a complete cached scan"
                )
            lines.append(
                "  Meaning: provider visibility window for this account, not a claimed publisher timestamp"
            )
        local_paths = app_local_path_details(item)
        if local_paths:
            lines.extend(["", "Local paths"])
            lines.extend(f"  {label}: {path}" for label, path in local_paths)
        if getattr(self, "debug_mode", False):
            prediction_reasons = (
                "\n".join(f"    - {reason}" for reason in item.prediction_reasons)
                if item.prediction_reasons
                else "    (none)"
            )
            lines.extend(
                [
                    "",
                    "Decision (debug)",
                    f"  Selected: {item.selected}",
                    f"  Status: {item.status}",
                    f"  Classification: {item.classification}",
                    f"  Prediction: {item.applicability_prediction or '(none)'}",
                    f"  Predicted HRESULT: {item.predicted_hresult or '(none)'}",
                    f"  Prediction confidence: {item.prediction_confidence or '(none)'}",
                    f"  Prediction source: {item.prediction_source or '(none)'}",
                    "  Prediction reasons:",
                    prediction_reasons,
                    f"  Guidance: {item.guidance or '(none)'}",
                    f"  Guidance URL: {item.guidance_url or '(none)'}",
                ]
            )
        if item.provider == PORTABLE_PROVIDER_KEY:
            path_state = (
                "yes"
                if item.portable_on_path is True
                else "no"
                if item.portable_on_path is False
                else "not checked"
            )
            lines.extend(
                [
                    "",
                    "Portable installation",
                    f"  Executable: {item.portable_executable or '(not available)'}",
                    f"  Scan root: {item.portable_scan_root or '(not available)'}",
                    f"  Detected by: {item.portable_detected_by or '(not recorded)'}",
                    f"  Format: {item.portable_format or '(not specified)'}",
                    f"  Publisher: {item.portable_publisher or '(not published)'}",
                    (
                        f"  Original filename: "
                        f"{item.portable_original_filename or '(not published)'}"
                    ),
                    f"  Declared homepage: {item.portable_homepage or '(not published)'}",
                    (
                        f"  Detection confidence: "
                        f"{item.portable_detection_confidence or '(not recorded)'}"
                    ),
                    f"  Evidence score: {item.portable_evidence_score}",
                    f"  Executable folder is on PATH: {path_state}",
                    "  Automatic update support: manual portable replacement only",
                ]
            )
            if item.portable_evidence_reasons and getattr(self, "debug_mode", False):
                lines.append("  Evidence:")
                lines.extend(f"    - {reason}" for reason in item.portable_evidence_reasons)
            if item.portable_removal_kind:
                lines.extend(
                    [
                        f"  Removal: delete the exact {item.portable_removal_kind}",
                        f"  Removal target: {item.portable_removal_target}",
                        f"  Why removal is offered: {item.portable_removal_reason}",
                    ]
                )
            else:
                lines.append(
                    "  Removal: not offered because ownership of a complete deletion "
                    "could not be proven"
                )
            if item.portable_catalog_checked_at:
                lines.extend(
                    [
                        "",
                        "Portable release information",
                        (
                            f"  WinGet package ID: "
                            f"{item.portable_catalog_package_id or '(no high-confidence match)'}"
                        ),
                        f"  Catalog name: {item.portable_catalog_name or '(not available)'}",
                        f"  Release-version clue: {item.available}",
                        (f"  Homepage: {item.portable_catalog_homepage or '(not published)'}"),
                        (
                            f"  Manifest installer URL: "
                            f"{item.portable_catalog_download_url or '(not published)'}"
                        ),
                        (
                            f"  Match basis: "
                            f"{item.portable_catalog_match_basis or '(none accepted)'}"
                        ),
                        "  Checked: "
                        + local_observation_time(item.portable_catalog_checked_at),
                        "  This is release information only; portable replacement remains manual.",
                    ]
                )
                if item.portable_catalog_error and getattr(self, "debug_mode", False):
                    lines.append(f"  Lookup note (debug): {item.portable_catalog_error}")
        elif item.provider == MICROSOFT_STORE_PROVIDER_KEY:
            exact_store_product = (
                item.source.casefold() == MICROSOFT_STORE_SOURCE
                and MICROSOFT_STORE_PRODUCT_ID_RE.fullmatch(item.package_id) is not None
            )
            lines.extend(
                [
                    "",
                    "Microsoft Store",
                    "  Account context: launching Windows account (never elevated)",
                    (
                        "  Update route: exact selective update through WinGet's msstore source"
                        if item.classification != CLASS_INVENTORY_ONLY
                        else "  Update route: Store-managed; use the row context menu to open updates"
                    ),
                    (
                        f"  Store product ID: {item.package_id}"
                        if exact_store_product
                        else "  Store product ID: not correlated by the public Store catalog"
                    ),
                ]
            )
        elif item.provider == WingetProvider.key:
            lines.extend(
                [
                    "",
                    "WinGet detail check",
                    f"  State: {self._winget_detail_check_state(item, hold_record)}",
                ]
            )
        lines.extend(
            [
                "",
                "Metadata",
                f"  Sources: {metadata_sources}",
                f"  Confidence: {item.metadata_confidence or '(none)'}",
                f"  Candidate key: {item.candidate_key}",
            ]
        )
        if hold_record:
            lines.extend(
                [
                    "",
                    "Attempt hold",
                    f"  Outcome: {hold_record.get('outcome', '')}",
                    f"  Classification: {hold_record.get('classification', '')}",
                    f"  Return code: {hold_record.get('returncode_hex', '')}",
                    f"  Count: {hold_record.get('count', 1)}",
                    "  First seen: "
                    + local_observation_time(str(hold_record.get("first_seen", ""))),
                    "  Last seen: "
                    + local_observation_time(
                        str(
                            hold_record.get(
                                "last_seen", hold_record.get("attempted_at", "")
                            )
                        )
                    ),
                    f"  Suppressed: {bool(hold_record.get('suppressed', False))}",
                ]
            )
            hold_hint = str(hold_record.get("status_hint", "")).strip()
            if hold_hint:
                lines.append(f"  Guidance: {hold_hint}")
            if winget_permission_repair_target(item, hold_record) is not None:
                remediation = hold_record.get("remediation", {})
                blocked_path = (
                    str(remediation.get("blocked_path", "")).strip()
                    if isinstance(remediation, Mapping)
                    else ""
                )
                lines.extend(
                    [
                        "",
                        "WinGet permission repair",
                        "  Create it: use Create repair script below, or right-click the "
                        "package row and choose Create WinGet permission repair script",
                        (
                            f"  Blocked path: {blocked_path}"
                            if blocked_path
                            else f"  Package folder: {item.installed_location}"
                        ),
                        "  The generated .cmd:",
                        "    - requires an administrator launch before changing anything",
                        "    - takes ownership of only this exact WinGet package folder",
                        "    - re-enables inherited permissions and grants your normal "
                        "Windows account Full Control",
                        "    - attempts to restore ownership to your normal Windows account",
                        "  It does not run automatically, install/uninstall/update the package, "
                        "or touch other WinGet package folders.",
                        "  After it succeeds: return here, release this package hold, then "
                        "retry the update.",
                    ]
                )
        if item.classification == CLASS_MIGRATION_REQUIRED:
            guidance = (
                powershell_preview_migration_guidance(item)
                if is_powershell_preview_msi_migration(item)
                else generic_migration_guidance(item)
            )
            lines.extend(["", guidance])
        if preferred_vector_style(item) or (icon_evidence and icon_evidence.get("generated_vector")):
            vector_style = str((icon_evidence or {}).get("generated_vector", ""))
            if vector_style not in V64_ICONS:
                vector_style = fallback_vector_style(item)
            # Runtime drawing strings exclude Python comments and string delimiters.
            script_characters = len("".join(V64_ICONS[vector_style].split()))
            lines.extend(["", "Icon artwork", f"  Displayed: built-in vector illustration ({vector_style})",
                          f"  Renderer: VPL64 {VPL64_ENGINE_VERSION} (language {VPL64_LANGUAGE_VERSION})",
                          f"  Script: {script_characters} characters (excluding whitespace and comments)",
                          "  Generated PNGs share the graphics cache; original package artwork is retained."])
            if icon_evidence:
                lines.append(f"  Cached bitmap: {icon_evidence.get('generated_png', '(not ready)')}")
        elif icon_evidence:
            lines.extend(
                [
                    "",
                    "Icon artwork",
                    f"  Best source file: {icon_evidence.get('source_file', '(unknown)')}",
                ]
            )
            if icon_evidence.get("metadata_ready"):
                source_width = int(icon_evidence.get("source_canvas_width", 0) or 0)
                source_height = int(icon_evidence.get("source_canvas_height", 0) or 0)
                visible_width = int(icon_evidence.get("source_visible_width", 0) or 0)
                visible_height = int(icon_evidence.get("source_visible_height", 0) or 0)
                rendered_width = int(icon_evidence.get("rendered_art_width", 0) or 0)
                rendered_height = int(icon_evidence.get("rendered_art_height", 0) or 0)
                output_width = int(icon_evidence.get("output_width", 0) or 0)
                output_height = int(icon_evidence.get("output_height", 0) or 0)
                outline_applied = bool(icon_evidence.get("adaptive_outline_applied"))
                outline_tone = str(icon_evidence.get("adaptive_outline_tone", "none"))
                lines.extend(
                    [
                        f"  Extracted canvas: {source_width} × {source_height} px",
                        f"  Visible source artwork: {visible_width} × {visible_height} px",
                        f"  Artwork fitted inside final icon cell: "
                        f"{rendered_width} × {rendered_height} px",
                        f"  Final icon cell (including transparent margin): "
                        f"{output_width} × {output_height} px",
                    ]
                )
                if icon_evidence.get("native_ico_frame_preserved"):
                    native_ico_width = int(icon_evidence.get("native_ico_frame_width", 0) or 0)
                    native_ico_height = int(icon_evidence.get("native_ico_frame_height", 0) or 0)
                    lines.append(
                        "  Native ICO frame preserved before scaling: "
                        f"{native_ico_width} × {native_ico_height} px"
                    )
                affirmative_properties = (
                    ("source_has_explicit_alpha_channel", "Explicit alpha channel"),
                    ("source_uses_transparency", "Transparency present"),
                    ("source_uses_partial_alpha", "Partial-alpha pixels present"),
                    ("alpha_cleanup_applied", "Alpha cleanup applied"),
                    ("normalized_with_gdiplus", "GDI+ format normalization"),
                )
                lines.extend(
                    f"  {label}: yes"
                    for key, label in affirmative_properties
                    if icon_evidence.get(key)
                )
                if icon_evidence.get("upscaled"):
                    try:
                        scale_x = float(icon_evidence["upscale_scale_x"])
                        scale_y = float(icon_evidence["upscale_scale_y"])
                    except (KeyError, TypeError, ValueError):
                        lines.append("  Bilinear upscaling: yes")
                    else:
                        if math.isfinite(scale_x) and math.isfinite(scale_y):
                            if math.isclose(scale_x, scale_y, rel_tol=0.001, abs_tol=0.001):
                                factor = f"{scale_x:.3f}".rstrip("0").rstrip(".")
                                factor_text = f"{factor}×"
                            else:
                                factor_x = f"{scale_x:.3f}".rstrip("0").rstrip(".")
                                factor_y = f"{scale_y:.3f}".rstrip("0").rstrip(".")
                                factor_text = f"{factor_x}× width, {factor_y}× height"
                            lines.append(f"  Bilinear upscaling: {factor_text}")
                        else:
                            lines.append("  Bilinear upscaling: yes")
                if outline_applied:
                    lines.append(f"  Adaptive contrast outline: yes ({outline_tone})")
            else:
                lines.append("  Processing details: being recorded in the background")
        return "\n".join(lines) + "\n"

    @staticmethod
    def _winget_detail_check_state(item: UpdateItem, hold_record: Mapping[str, Any] | None) -> str:
        if item.provider != WingetProvider.key:
            return "Not applicable to this provider."
        if hold_record:
            return (
                "Learned from a previous exact failed attempt. This local attempt-hold "
                "record keeps the same candidate from being silently recommended again "
                "until the hold is released or the package/version candidate changes."
            )
        if item.applicability_prediction == PREDICTION_PENDING:
            return (
                "Background WinGet manifest check is still pending. The row is kept "
                "unchecked until details confirm it is an ordinary update."
            )
        if item.applicability_prediction == PREDICTION_UNKNOWN:
            return (
                "WinGet manifest details were unavailable or inconclusive. Use Test once "
                "for diagnostic evidence, or rescan to let the background check retry."
            )
        if item.prediction_source:
            return (
                f"Checked through {item.prediction_source}; confidence "
                f"{item.prediction_confidence or 'not scored'}."
            )
        return "Basic WinGet inventory only; no extra manifest check was needed."

    @staticmethod
    def status_tooltip_text(item: UpdateItem) -> str:
        lines = [
            f"{item.name}",
            f"Status: {item.status}",
            f"Classification: {item.classification}",
        ]
        if item.provider == PORTABLE_PROVIDER_KEY:
            path_state = (
                "Yes"
                if item.portable_on_path is True
                else "No"
                if item.portable_on_path is False
                else "Not checked"
            )
            lines.extend(
                [
                    "",
                    f"Executable: {item.portable_executable or '(not available)'}",
                    f"Detected by: {item.portable_detected_by or '(not recorded)'}",
                    (
                        f"Identity: {item.portable_format or 'local portable evidence'} · "
                        f"{item.portable_detection_confidence or 'unscored'} confidence"
                    ),
                    f"Executable folder on PATH: {path_state}",
                    "",
                    "Updates remain manual so the chosen portable layout is preserved.",
                ]
            )
            if item.portable_catalog_checked_at:
                lines.extend(
                    [
                        "",
                        (
                            f"WinGet catalog: {item.portable_catalog_package_id} ({item.available})"
                            if item.portable_catalog_package_id
                            else f"Release clue: {item.available}"
                            if item.available not in {"", "Not checked", "Not found"}
                            else "Release check: no high-confidence version found"
                        ),
                    ]
                )
                if item.portable_catalog_homepage:
                    lines.append(f"Homepage: {item.portable_catalog_homepage}")
                if item.portable_catalog_download_url:
                    lines.append(f"WinGet installer URL: {item.portable_catalog_download_url}")
                if item.portable_catalog_match_basis:
                    lines.append(f"Match basis: {item.portable_catalog_match_basis}")
            if item.portable_removal_kind:
                lines.extend(
                    [
                        "",
                        f"Uninstall available: delete exact {item.portable_removal_kind}",
                        f"Target: {item.portable_removal_target}",
                        item.portable_removal_reason,
                    ]
                )
            else:
                lines.extend(
                    [
                        "",
                        "Uninstall is not offered because a complete, unambiguous "
                        "deletion target was not proven.",
                    ]
                )
            return "\n".join(lines)
        if item.provider == MICROSOFT_STORE_PROVIDER_KEY:
            lines.extend(
                [
                    "",
                    "Account: the Windows account that launched WinDevPilot",
                    "Elevation: never; Store identity is account-specific",
                    (
                        "Update route: exact selective WinGet msstore operation"
                        if item.classification != CLASS_INVENTORY_ONLY
                        else "Update route: Microsoft Store updates page from the context menu"
                    ),
                ]
            )
            if item.source.casefold() == MICROSOFT_STORE_SOURCE:
                lines.append(f"Store product ID: {item.package_id}")
            else:
                lines.append("Store product ID: not correlated by the public catalog")
            return "\n".join(lines)
        prediction = item.applicability_prediction or PREDICTION_ORDINARY
        if prediction != PREDICTION_ORDINARY or item.prediction_confidence:
            lines.extend(
                [
                    f"Prediction: {prediction}",
                    f"Confidence: {item.prediction_confidence or 'not scored'}",
                ]
            )
        if item.predicted_hresult:
            lines.append(f"Expected WinGet result: {item.predicted_hresult}")
        installed_size = human_size_from_kb(item.installed_size_kb)
        if installed_size:
            lines.append(f"Installed size: about {installed_size} from Windows uninstall metadata")
        if item.classification == CLASS_MIGRATION_REQUIRED:
            lines.extend(
                [
                    "",
                    "Meaning: this is not a normal in-place update.",
                    (
                        f"Installed locally as {item.installed_technology or 'unknown'} "
                        f"for {item.installed_for or item.scope or 'unknown scope'}; "
                        f"available package is {item.available_technology or 'unknown'}."
                    ),
                    (
                        "WinGet generally cannot perform installer-technology migrations "
                        "as one normal silent upgrade, so WinDevPilot holds it for review."
                    ),
                    (
                        "PowerShell Preview MSI migrations can expose copyable guided "
                        "commands; other migrations are explanation-only."
                    ),
                ]
            )
        elif item.classification == CLASS_VENDOR_MANAGED:
            lines.extend(
                [
                    "",
                    "Meaning: this app normally updates through its own updater.",
                    "WinGet probes are expected to be diagnostic, not reliable fixes.",
                ]
            )
        elif item.classification == CLASS_DUPLICATE_INSTALL:
            lines.extend(
                [
                    "",
                    "Meaning: more than one user/machine registration is visible.",
                    "Resolve which install should remain before expecting a clean update.",
                ]
            )
        elif item.classification == CLASS_AMBIGUOUS_IDENTITY:
            lines.extend(
                [
                    "",
                    "Meaning: this package-manager entry does not identify one safely "
                    "serviceable installation.",
                ]
            )
        elif item.classification == CLASS_SCOPE_OR_APPLICABILITY:
            lines.extend(
                [
                    "",
                    "Meaning: this exact installed target has not accepted the available "
                    "installer in recent evidence.",
                ]
            )
        elif item.classification == CLASS_MANUAL_REPAIR:
            lines.extend(
                [
                    "",
                    "Meaning: the existing installation needs a narrow local repair before "
                    "its package manager can replace it.",
                ]
            )
            if item.provider == RustupProvider.key:
                lines.append(
                    "A damaged Rust toolchain reinstall is a separate manual system repair, "
                    "not an ordinary retry; WinDevPilot will not run it automatically."
                )
            elif item.provider == WingetProvider.key:
                lines.append(
                    "For a detected WinGet package-permission failure, right-click the package "
                    "to create a reviewable exact-folder repair script."
                )
        elif item.applicability_prediction == PREDICTION_PENDING:
            lines.extend(
                [
                    "",
                    "Meaning: WinGet found an update, but the background manifest check "
                    "has not confirmed whether it is an ordinary update yet.",
                ]
            )
        elif item.applicability_prediction == PREDICTION_UNKNOWN:
            lines.extend(
                [
                    "",
                    "Meaning: WinGet manifest evidence was unavailable or inconclusive. "
                    "This row is visible for review but left out of normal recommendations.",
                ]
            )
        elif item.classification == CLASS_MANIFEST_LAG:
            lines.extend(
                [
                    "",
                    "Meaning: WinGet rejected the installer because its manifest hash did "
                    "not match the current vendor download.",
                    (
                        "This is treated as transient manifest lag, not as a durable "
                        "problem with this specific package. Retry later or use the "
                        "vendor's own updater; WinDevPilot will not bypass the hash check."
                    ),
                ]
            )
        elif item.classification == CLASS_SIMPLE_UPGRADE:
            lines.extend(["", "Meaning: this package is eligible for normal Update selected."])
        if item.prediction_reasons:
            lines.append("")
            lines.append("Evidence:")
            lines.extend(f"- {reason}" for reason in item.prediction_reasons[:5])
        identity_bits = []
        if item.installed_for:
            identity_bits.append(f"installed for {item.installed_for}")
        if item.installed_technology:
            identity_bits.append(f"installed technology {item.installed_technology}")
        if item.available_technology:
            identity_bits.append(f"available technology {item.available_technology}")
        if identity_bits:
            lines.extend(["", "Identity: " + "; ".join(identity_bits)])
        if item.guidance:
            lines.extend(["", "Advice:", item.guidance])
        if item.guidance_url:
            lines.append(f"Reference: {item.guidance_url}")
        return "\n".join(lines)

    def select_recommended(self) -> None:
        if self.busy:
            return
        query = self.search_var.get().strip()
        for item in self.items.values():
            if self._matches_filter(item, query):
                item.selected = self._item_is_recommended_selectable(item)
                self._selection_touched_keys.add(item.key)
        self._rebuild_tree()

    def select_all(self) -> None:
        if self.busy:
            return
        query = self.search_var.get().strip()
        for item in self.items.values():
            if self._matches_filter(item, query) and self._item_is_actionable(item):
                item.selected = True
                self._selection_touched_keys.add(item.key)
        self._rebuild_tree()

    def select_none(self) -> None:
        if self.busy:
            return
        query = self.search_var.get().strip()
        for item in self.items.values():
            if self._matches_filter(item, query):
                item.selected = False
                self._selection_touched_keys.add(item.key)
        self._rebuild_tree()

    def _ignore_item(self, item: UpdateItem) -> None:
        """Persistently hide one update chosen from its context menu."""

        if self.busy or self._last_scan_all_packages or item.key not in self.items:
            return
        ignored = set(map(str.casefold, self.settings.data.get("ignored", [])))
        ignored.add(item.ignore_key)
        self.settings.data["ignored"] = sorted(ignored)
        self.settings.save()
        self.items.pop(item.key, None)
        self._selection_touched_keys.discard(item.key)
        self._rebuild_tree()
        self.summary_var.set(f"Ignored {item.name}; restore it from Manage ignores")
        self._append_log(
            f"Ignored update: {item.name} ({item.package_id})",
            show_in_ui=False,
        )

    def manage_ignores(self) -> None:
        tk, ttk = self.tk, self.ttk
        px = self.visuals.px
        window = self._create_toplevel(self.root)
        window.title("Manage ignored updates")
        window.geometry(self.visuals.geometry_from_dips("680x400"))
        window.transient(self.root)
        frame = ttk.Frame(window, padding=px(14))
        frame.pack(fill="both", expand=True)
        ttk.Label(
            frame,
            text="Ignored packages stay hidden across versions. Select entries to restore.",
        ).pack(anchor="w", pady=(0, px(8)))
        listbox = tk.Listbox(frame, selectmode="extended", font=self._mono_font(10))
        self._configure_listbox(listbox)
        listbox.pack(fill="both", expand=True)
        self._bind_widget_tooltip(
            listbox,
            "Select ignored package entries here, then use Restore selected to show them again.",
        )
        ignored = list(self.settings.data.get("ignored", []))
        for value in ignored:
            listbox.insert("end", value)

        def restore() -> None:
            remove = {ignored[index] for index in listbox.curselection()}
            self.settings.data["ignored"] = [value for value in ignored if value not in remove]
            self.settings.save()
            window.destroy()
            self.scan()

        self._button(
            frame,
            text="Restore selected",
            command=restore,
            tooltip="Unhide the selected ignored updates and rescan.",
        ).pack(anchor="e", pady=(px(10), 0))

    def manage_attempt_holds(self) -> None:
        tk, ttk = self.tk, self.ttk
        px = self.visuals.px
        active_keys = {item.candidate_key for item in self.items.values()}
        summary = attempt_hold_scan_summary(self.settings.data, active_keys)
        active = list(summary["active"])
        stale = list(summary["stale"])
        window = self._create_toplevel(self.root)
        window.title("Holds")
        window.geometry(self.visuals.geometry_from_dips("820x440"))
        window.transient(self.root)
        frame = ttk.Frame(window, padding=px(14))
        frame.pack(fill="both", expand=True)
        ttk.Label(
            frame,
            text=(
                "Holds are safety pauses, not ignores. Entries appear here when "
                "WinDevPilot has temporarily stopped retrying an exact update candidate "
                "after a risky or repeated failure, or when a fresh verification scan "
                "contradicts a reported success. Active holds keep that candidate unchecked; "
                "stale holds are old records for packages no longer visible in the current "
                "scan. Release a hold only when you want the app to try that same candidate "
                "again."
            ),
            wraplength=760,
        ).pack(anchor="w", pady=(0, px(8)))
        listbox = tk.Listbox(frame, selectmode="extended", font=self._mono_font(10))
        self._configure_listbox(listbox)
        listbox.pack(fill="both", expand=True)
        self._bind_widget_tooltip(
            listbox,
            (
                "Select active holds to release them for another deliberate try, or "
                "select stale holds to remove old records for packages no longer visible."
            ),
        )
        rows: list[tuple[str, str]] = []
        for record in active:
            label = (
                f"active  {record['package_id'] or record['name']}  "
                f"{record['classification']}  count={record['count']}"
            )
            rows.append((str(record["candidate_key"]), "active"))
            listbox.insert("end", label)
        for record in stale:
            label = (
                f"stale   {record['package_id'] or record['name']}  "
                f"{record['classification']}  count={record['count']}"
            )
            rows.append((str(record["candidate_key"]), "stale"))
            listbox.insert("end", label)
        if not rows:
            listbox.insert("end", "No attempt holds are currently stored.")
        if summary["stale_omitted"]:
            listbox.insert("end", f"... {summary['stale_omitted']} stale hold(s) omitted")

        buttons = ttk.Frame(frame)
        buttons.pack(fill="x", pady=(px(10), 0))

        def selected_hold_keys() -> set[str]:
            return {rows[index][0] for index in listbox.curselection() if index < len(rows)}

        def release_selected() -> None:
            selected_keys = selected_hold_keys()
            if not selected_keys:
                self._notify_user(
                    "Select one or more holds to release.",
                    summary="Select holds to release",
                )
                return
            released = release_attempt_holds(self.settings.data, selected_keys, self.logger)
            if released:
                self.settings.save()
                self._append_log(
                    f"Released {released} attempt hold(s); affected package(s) may be retryable after rescan"
                )
            window.destroy()
            self.scan()

        def clear_selected_stale() -> None:
            selected_keys = {
                rows[index][0]
                for index in listbox.curselection()
                if index < len(rows) and rows[index][1] == "stale"
            }
            if not selected_keys:
                self._notify_user(
                    "Select one or more stale holds to clear.",
                    summary="Select stale holds to clear",
                )
                return
            removed = prune_stale_attempt_holds(
                self.settings.data, active_keys, self.logger, keys=selected_keys
            )
            if removed:
                self.settings.save()
                self._append_log(f"Cleared {removed} stale attempt hold(s)")
            window.destroy()
            self.scan()

        def clear_all_stale() -> None:
            removed = prune_stale_attempt_holds(self.settings.data, active_keys, self.logger)
            if not removed:
                self._notify_user(
                    "There are no stale attempt holds to clear.",
                    summary="No stale attempt holds to clear",
                )
                return
            self.settings.save()
            self._append_log(f"Cleared {removed} stale attempt hold(s)")
            window.destroy()
            self.scan()

        self._button(
            buttons,
            text="Clear selected stale",
            command=clear_selected_stale,
            tooltip="Remove only selected stale hold records. Active holds are preserved.",
        ).pack(side="right", padx=(px(6), 0))
        self._button(
            buttons,
            text="Release selected holds",
            command=release_selected,
            tooltip=(
                "Remove selected hold records, including active ones, so those exact "
                "candidates can be selected/retried after the rescan."
            ),
        ).pack(side="right", padx=(px(6), 0))
        self._button(
            buttons,
            text="Clear all stale",
            command=clear_all_stale,
            tooltip="Remove all stale hold records for packages no longer visible in the scan.",
        ).pack(side="right")

    def _current_winget_ids_for_suggestions(self) -> set[str] | None:
        """Reuse the latest successful WinGet provider batch despite unrelated failures."""

        if (
            self._last_scan_completed_at is None
            or WingetProvider.key not in self._scan_current_provider_keys
        ):
            return None
        rows = self._scan_provider_inventory_batches.get(WingetProvider.key)
        if rows is None:
            return None
        return {
            item.package_id.casefold()
            for item in rows
            if valid_package_id(item.package_id)
        }

    def show_suggested_installs(self) -> None:
        tk, ttk = self.tk, self.ttk
        px = self.visuals.px
        window = self._create_toplevel(self.root)
        window.title("Suggested developer installs")
        window.geometry(self.visuals.geometry_from_dips("900x560"))
        window.transient(self.root)
        frame = ttk.Frame(window, padding=px(16))
        frame.pack(fill="both", expand=True)
        ttk.Label(
            frame,
            text="Suggested developer installs",
            font=self._ui_font(15, semibold=True, display=True),
        ).pack(anchor="w")
        ttk.Label(
            frame,
            text=(
                "Curated common Windows developer tools missing from WinGet's "
                "user/machine inventory. Right-click a tool to install it through an "
                "available package manager, or copy its exact command."
            ),
            wraplength=820,
            style="Subtitle.TLabel",
        ).pack(anchor="w", pady=(px(2), px(10)))
        status = tk.StringVar(value="Checking WinGet inventory...")
        ttk.Label(frame, textvariable=status, style="Subtitle.TLabel").pack(anchor="w")
        body = ttk.Frame(frame)
        body.pack(fill="both", expand=True, pady=(px(8), 0))
        listbox = tk.Listbox(body, selectmode="extended", font=self._mono_font(10))
        self._configure_listbox(listbox)
        scrollbar = ttk.Scrollbar(body, orient="vertical", command=listbox.yview)
        listbox.configure(yscrollcommand=scrollbar.set)
        listbox.pack(side="left", fill="both", expand=True)
        scrollbar.pack(side="right", fill="y")
        self._bind_widget_tooltip(
            listbox,
            (
                "Right-click one missing developer tool to install it through its available "
                "package manager. The buttons below copy commands without running them."
            ),
        )
        listbox.insert("end", "Checking installed WinGet package IDs...")
        displayed: list[PackageSuggestion] = []
        detail = tk.Text(
            frame,
            height=5,
            wrap="word",
            font=self._mono_font(9),
            relief="solid",
            borderwidth=1,
        )
        self._configure_text_panel(detail)
        detail.pack(fill="x", pady=(px(8), 0))
        detail.insert("1.0", "Select a suggested package to see its summary and exact command.")
        detail.configure(state="disabled")
        self._bind_widget_tooltip(
            detail,
            "Shows the selected suggestion's purpose, homepage, and exact command to copy.",
        )

        def set_detail(text: str) -> None:
            detail.configure(state="normal")
            detail.delete("1.0", "end")
            detail.insert("1.0", text)
            detail.configure(state="disabled")

        def update_detail(_event: Any | None = None) -> None:
            suggestions = selected_suggestions()
            if not suggestions:
                set_detail("Select a suggested package to see its summary and exact command.")
                return
            suggestion = suggestions[0]
            metadata_lines = [
                f"Tier: {suggestion.tier.title()}",
            ]
            if suggestion.profiles:
                metadata_lines.append(f"Best for: {', '.join(suggestion.profiles)}")
            if suggestion.account_required:
                metadata_lines.append("Account: required")
            if suggestion.service_cost != "none":
                metadata_lines.append(f"Cost: {suggestion.service_cost}")
            if suggestion.large_download:
                metadata_lines.append("Download/storage: potentially large")
            if suggestion.prerequisites:
                metadata_lines.append(f"Requires: {', '.join(suggestion.prerequisites)}")
            if suggestion.system_changes:
                metadata_lines.append(f"System impact: {'; '.join(suggestion.system_changes)}")
            set_detail(
                "\n".join(
                    [
                        f"{suggestion.title} ({suggestion.winget_id})",
                        f"Category: {suggestion.category}",
                        *metadata_lines,
                        f"Summary: {suggestion.summary}",
                        f"Homepage: {suggestion.homepage}",
                        "",
                        suggestion_install_command(suggestion),
                    ]
                )
            )

        listbox.bind("<<ListboxSelect>>", update_detail)

        def selected_suggestions() -> list[PackageSuggestion]:
            return [
                displayed[index] for index in listbox.curselection() if 0 <= index < len(displayed)
            ]

        def copy_commands(suggestions: Sequence[PackageSuggestion], label: str) -> None:
            if not suggestions:
                self._notify_user(
                    "Select one or more suggested packages first.",
                    summary="Select suggested packages first",
                )
                return
            commands = "\n".join(suggestion_install_command(item) for item in suggestions)
            self._copy_text(commands, log_message=f"Copied {label} suggested install command(s)")

        def finish_install(suggestion: PackageSuggestion, success: bool) -> None:
            nonlocal displayed
            if not success or not window.winfo_exists():
                return
            displayed = [
                item
                for item in displayed
                if item.winget_id.casefold() != suggestion.winget_id.casefold()
            ]
            listbox.delete(0, "end")
            if displayed:
                for item in displayed:
                    listbox.insert(
                        "end",
                        f"{item.category:<20}  {item.title:<34}  {item.winget_id}",
                    )
                status.set(f"{len(displayed)} suggested install(s) not detected.")
            else:
                listbox.insert("end", "All curated suggestions are already present.")
                status.set("All curated suggestions are already present.")
            update_detail()

        def populate_context_menu(menu: Any) -> bool:
            try:
                index = int(listbox.index("active"))
            except (ValueError, tk.TclError):
                return False
            if not (0 <= index < len(displayed)):
                return False
            suggestion = displayed[index]
            route = self._suggested_install_route(suggestion)
            if route is None:
                return False
            provider, _command = route
            menu.add_command(
                label=f"Install {suggestion.title} through {provider.label}",
                command=lambda item=suggestion: self._request_suggested_install(
                    item,
                    lambda success, installed=item: finish_install(installed, success),
                ),
                state="disabled" if self.busy else "normal",
            )
            return True

        listbox._wdp_populate_context_menu = populate_context_menu

        buttons = ttk.Frame(frame)
        buttons.pack(fill="x", pady=(px(10), 0))
        copy_selected_button = self._button(
            buttons,
            text="Copy selected commands",
            command=lambda: copy_commands(selected_suggestions(), "selected"),
            tooltip="Copy exact winget install commands for the selected suggestions.",
        )
        copy_all_button = self._button(
            buttons,
            text="Copy all missing commands",
            command=lambda: copy_commands(displayed, "all missing"),
            tooltip="Copy exact winget install commands for every missing suggestion shown.",
        )
        copy_selected_button.pack(side="left")
        copy_all_button.pack(side="left", padx=(px(8), 0))
        recheck_button = self._button(
            buttons,
            text="Recheck",
            command=lambda: check_inventory(force=True),
            busy_disabled=False,
            tooltip=(
                "Run fresh user- and machine-scope WinGet inventory checks. Use this after "
                "installing a copied command outside WinDevPilot."
            ),
        )
        recheck_button.pack(side="left", padx=(px(8), 0))
        self._button(
            buttons,
            text="Close",
            command=window.destroy,
            tooltip="Close this suggested installs window.",
        ).pack(side="right")

        inventory_generation = 0

        def finish(
            installed_ids: set[str], warnings: list[str], source_label: str, generation: int,
            error: str = "",
        ) -> None:
            nonlocal displayed
            if not window.winfo_exists() or generation != inventory_generation:
                return
            recheck_button.configure(state="normal")
            if error:
                # An unavailable inventory does not mean every suggestion is absent.
                # Keep the previous results visible and allow another check.
                status.set("Inventory check failed. Previous results retained; use Recheck to retry.")
                self._append_log("Suggested installs inventory check failed: " + error)
                self.logger.event("suggested_installs_check_failed", error=error)
                return
            available_commands = available_suggestion_presence_commands()
            displayed = build_missing_package_suggestions(
                installed_ids,
                available_commands,
            )
            listbox.delete(0, "end")
            if displayed:
                for suggestion in displayed:
                    listbox.insert(
                        "end",
                        (
                            f"{suggestion.category:<20}  {suggestion.title:<34}  "
                            f"{suggestion.winget_id}"
                        ),
                    )
                status.set(
                    f"{len(displayed)} suggested install(s) not detected; "
                    f"{len(PACKAGE_SUGGESTIONS) - len(displayed)} already present "
                    f"({source_label})."
                )
            else:
                listbox.insert("end", "All curated suggestions are already present.")
                status.set("All curated suggestions are already present.")
            update_detail()
            if warnings:
                self._append_log("Suggested installs warning: " + "; ".join(warnings[:3]))
            self.logger.event(
                "suggested_installs_checked",
                installed_id_count=len(installed_ids),
                missing=[item.to_dict() for item in displayed],
                warnings=warnings,
                inventory_source=source_label,
                available_presence_commands=sorted(available_commands),
            )

        def check_inventory(*, force: bool = False) -> None:
            nonlocal inventory_generation
            inventory_generation += 1
            generation = inventory_generation
            recheck_button.configure(state="disabled")
            if not force:
                current_ids = self._current_winget_ids_for_suggestions()
                if current_ids is not None:
                    finish(current_ids, [], "current scan", generation)
                    return
            status.set("Rechecking WinGet inventory…" if force else "Checking WinGet inventory…")

            def worker() -> None:
                error = ""
                try:
                    installed_ids, warnings = winget_installed_ids_for_suggestions(
                        bypass_recent_cache=force
                    )
                except Exception as exc:
                    installed_ids, warnings = set(), []
                    error = f"{type(exc).__name__}: {exc}"
                self.events.put(
                    (
                        "ui_callback",
                        (
                            finish,
                            (
                                installed_ids,
                                warnings,
                                "fresh WinGet check" if force else "WinGet inventory",
                                generation,
                                error,
                            ),
                        ),
                    )
                )

            threading.Thread(target=worker, name="wdp-suggested-installs", daemon=True).start()

        check_inventory()

    def configure_providers(self) -> None:
        tk, ttk = self.tk, self.ttk
        px = self.visuals.px
        scan_running_when_opened = self.busy and self._busy_kind == "scan"
        read_only_while_busy = self.busy and not scan_running_when_opened
        window = self._create_toplevel(self.root)
        window.title("Package-manager providers")
        window.geometry(self.visuals.geometry_from_dips("720x620"))
        window.minsize(px(620), px(500))
        window.transient(self.root)
        frame = ttk.Frame(window, padding=px(18))
        frame.pack(fill="both", expand=True)
        ttk.Label(
            frame,
            text="Choose which package managers are scanned.",
            font=self._ui_font(14, semibold=True, display=True),
        ).pack(anchor="w")
        ttk.Label(
            frame,
            text=(
                "Provider checkbox changes are saved immediately. Use Save and rescan "
                "to close this dialog and apply them to the update list. pip is off by "
                "default because bulk Python upgrades can cross major versions and "
                "disturb shared environments. Project .venv and uv/uv pip environments "
                "are intentionally not scanned here."
            ),
            wraplength=540,
            style="Body.TLabel",
        ).pack(anchor="w", pady=(px(4), px(12)))
        if scan_running_when_opened:
            ttk.Label(
                frame,
                text=(
                    "The current scan keeps the choices it started with. Changes made now are "
                    "saved for the next scan, and the Scan button will indicate that a refresh "
                    "is needed."
                ),
                wraplength=540,
                style="Body.TLabel",
            ).pack(anchor="w", pady=(0, px(8)))
        elif read_only_while_busy:
            ttk.Label(
                frame,
                text=(
                    "A package operation is running, so provider choices are shown read-only. "
                    "Change them after WinDevPilot returns to idle."
                ),
                wraplength=540,
                style="Body.TLabel",
            ).pack(anchor="w", pady=(0, px(8)))
        ttk.Label(
            frame,
            text="Tip: resize this window or scroll the provider list if more managers are added.",
            style="Body.TLabel",
        ).pack(anchor="w", pady=(0, px(8)))
        variables: dict[str, Any] = {}

        def save_provider_toggle(provider_key: str, variable: Any) -> None:
            self.settings.data.setdefault("providers", {})[provider_key] = bool(variable.get())
            self.settings.save()
            self._mark_scan_refresh_needed(
                f"Provider setting changed: {self.providers[provider_key].label}"
            )
            self._append_log(
                f"Provider setting saved: {provider_key}="
                f"{self.settings.data['providers'][provider_key]}",
                show_in_ui=False,
            )
            self.logger.event(
                "provider_setting_saved",
                provider=provider_key,
                enabled=bool(self.settings.data["providers"][provider_key]),
            )

        def save_elevation_toggle() -> None:
            self.settings.data["auto_elevate"] = bool(elevate.get())
            self.settings.save()
            self._mark_scan_refresh_needed("Elevation setting changed")
            self._append_log(
                f"Elevation setting saved: auto_elevate={bool(elevate.get())}",
                show_in_ui=False,
            )
            self.logger.event("elevation_setting_saved", enabled=bool(elevate.get()))

        provider_area = ttk.Frame(frame)
        provider_area.pack(fill="both", expand=True)
        provider_canvas = tk.Canvas(
            provider_area,
            highlightthickness=0,
            bd=0,
        )
        self._register_theme_widget(provider_canvas, background="window")
        provider_scrollbar = ttk.Scrollbar(
            provider_area,
            orient="vertical",
            command=provider_canvas.yview,
        )
        provider_list = ttk.Frame(provider_canvas)
        provider_window_id = provider_canvas.create_window(
            (0, 0),
            window=provider_list,
            anchor="nw",
        )
        provider_canvas.configure(yscrollcommand=provider_scrollbar.set)
        provider_canvas.grid(row=0, column=0, sticky="nsew")
        provider_scrollbar.grid(row=0, column=1, sticky="ns")
        provider_area.columnconfigure(0, weight=1)
        provider_area.rowconfigure(0, weight=1)

        def update_provider_scrollregion(_event: Any | None = None) -> None:
            provider_canvas.configure(scrollregion=provider_canvas.bbox("all"))

        def update_provider_width(event: Any) -> None:
            provider_canvas.itemconfigure(provider_window_id, width=event.width)

        def wheel_provider_list(event: Any) -> str:
            event_delta = int(getattr(event, "delta", 0) or 0)
            if not event_delta:
                return "break"
            direction = -1 if event_delta > 0 else 1
            units = max(1, abs(event_delta) // 120)
            provider_canvas.yview_scroll(direction * units, "units")
            return "break"

        provider_list.bind("<Configure>", update_provider_scrollregion, add="+")
        provider_canvas.bind("<Configure>", update_provider_width, add="+")
        # Child labels and toggle rows have their own bind tags, so a
        # canvas-only wheel handler works only over the occasional empty patch.
        # The toplevel bind tag receives wheel input from every dialog child.
        window.bind("<MouseWheel>", wheel_provider_list, add="+")

        for key, provider in self.providers.items():
            if not provider.configurable:
                continue
            available = provider.available()
            variable = tk.BooleanVar(
                value=bool(self.settings.data["providers"].get(key, provider.default_enabled))
            )
            variables[key] = variable
            label = provider.label + ("" if available else "  (not installed)")
            row = self._provider_toggle_row(
                provider_list,
                label=label,
                variable=variable,
                available=available,
                read_only=read_only_while_busy,
                command=lambda provider_key=key, provider_var=variable: save_provider_toggle(
                    provider_key, provider_var
                ),
                tooltip=self._provider_tooltip(key, provider.label, available=available),
            )
            row.pack(fill="x", anchor="w", pady=px(4))
        elevate = tk.BooleanVar(value=bool(self.settings.data.get("auto_elevate", True)))
        elevation_context = (
            "This is an administrator account running with its normal filtered UAC token, "
            "so the prompt normally asks for consent in the same account. "
            if self.token_elevation_type == "limited"
            else ""
        )
        ttk.Separator(frame).pack(fill="x", pady=px(12))
        elevate_row = self._provider_toggle_row(
            frame,
            label="Allow one UAC prompt for selected machine updates when needed",
            variable=elevate,
            available=True,
            read_only=read_only_while_busy,
            command=save_elevation_toggle,
            tooltip=(
                elevation_context
                + "When enabled, selected machine-scoped WinGet updates are batched into "
                "one elevated helper run when this process is not already elevated. An "
                "administrator process runs eligible machine updates directly; this setting "
                "then applies only to a future non-elevated launch."
            ),
        )
        elevate_row.pack(fill="x", anchor="w", pady=(px(2), 0))

        def save() -> None:
            self.settings.data["providers"] = {
                key: bool(variable.get()) for key, variable in variables.items()
            }
            self.settings.data["auto_elevate"] = bool(elevate.get())
            self.settings.save()
            self.logger.event(
                "provider_settings_saved",
                providers=dict(self.settings.data["providers"]),
                auto_elevate=bool(self.settings.data["auto_elevate"]),
            )
            window.destroy()
            if not scan_running_when_opened:
                self.scan()

        footer = ttk.Frame(frame)
        footer.pack(fill="x", pady=(px(18), 0))
        save_button = self._button(
            footer,
            text="Close" if scan_running_when_opened else "Save and rescan",
            command=save,
            state="disabled" if read_only_while_busy else "normal",
            tooltip=(
                "Close this dialog. Changes are already saved; run Scan after the current scan "
                "finishes to apply them."
                if scan_running_when_opened
                else "Save provider choices, then run a fresh read-only scan."
                if not read_only_while_busy
                else "Provider choices are read-only while a scan or update is running."
            ),
        )
        save_button.pack(side="right", padx=(0, px(12)))

    def _refresh_open_toolchain_health(self) -> None:
        window = self._toolchain_health_window
        refresh = self._toolchain_health_refresh
        try:
            if window is not None and window.winfo_exists() and refresh is not None:
                refresh()
        except self.tk.TclError:
            self._toolchain_health_window = None
            self._toolchain_health_refresh = None

    def show_toolchain_health(self) -> None:
        tk, ttk = self.tk, self.ttk
        px = self.visuals.px
        existing = self._toolchain_health_window
        try:
            if existing is not None and existing.winfo_exists():
                existing.lift()
                existing.focus_set()
                self._refresh_open_toolchain_health()
                return
        except tk.TclError:
            pass

        window = self._create_toplevel(self.root)
        self._toolchain_health_window = window
        window.title("Developer toolchain health")
        window.geometry(self.visuals.geometry_from_dips("860x560"))
        window.transient(self.root)
        frame = ttk.Frame(window, padding=px(14))
        frame.pack(fill="both", expand=True)
        ttk.Label(
            frame,
            text="Developer toolchain health",
            font=self._ui_font(14, semibold=True, display=True),
        ).pack(anchor="w")
        ttk.Label(
            frame,
            text=(
                "Read-only path/version probes for common developer tools. "
                "This panel never updates packages and never scans project environments."
            ),
            style="Subtitle.TLabel",
            wraplength=790,
        ).pack(anchor="w", pady=(px(2), px(10)))
        text_frame = ttk.Frame(frame)
        text_frame.pack(fill="both", expand=True)
        text = tk.Text(
            text_frame,
            wrap="none",
            font=self._mono_font(9),
            relief="solid",
            borderwidth=1,
        )
        self._configure_text_panel(text)
        yscroll = ttk.Scrollbar(text_frame, orient="vertical", command=text.yview)
        xscroll = ttk.Scrollbar(text_frame, orient="horizontal", command=text.xview)
        text.configure(yscrollcommand=yscroll.set, xscrollcommand=xscroll.set)
        text.grid(row=0, column=0, sticky="nsew")
        yscroll.grid(row=0, column=1, sticky="ns")
        xscroll.grid(row=1, column=0, sticky="ew")
        text_frame.columnconfigure(0, weight=1)
        text_frame.rowconfigure(0, weight=1)
        self._configure_health_tags(text)
        text.insert("1.0", "Scanning developer toolchain paths and versions...\n", "health_title")
        text.configure(state="disabled")
        buttons = ttk.Frame(frame)
        buttons.pack(fill="x", pady=(px(10), 0))
        refresh_button = self._button(
            buttons,
            text="Refresh",
            command=lambda: start_scan("manual"),
            busy_disabled=False,
            tooltip="Run the read-only tool path and version checks again.",
        )
        refresh_button.pack(side="left")
        self._button(
            buttons,
            text="Close",
            command=window.destroy,
            tooltip="Close this read-only health panel.",
        ).pack(side="right")

        def finish(
            rows: list[dict[str, Any]],
            generation: int,
            reason: str,
            path_report: WindowsPathRefreshReport,
        ) -> None:
            if generation != self._toolchain_health_generation or not window.winfo_exists():
                return
            healthy_tools = {
                str(row["name"]).casefold()
                for row in rows
                if row["found"] and row["returncode"] == 0 and not row.get("timed_out")
            }
            refresh_button.configure(state="normal")
            text.configure(state="normal")
            text.delete("1.0", "end")
            text.insert("end", "Toolchain Health (read-only)\n", "health_title")
            text.insert(
                "end",
                f"Generated: {datetime_display_timestamp(dt.datetime.now().astimezone())}\n\n",
                "health_dim",
            )
            if path_advisory := windows_path_refresh_advisory(path_report):
                text.insert("end", "PATH advisory\n", "health_warn")
                text.insert("end", f"  {path_advisory}\n\n", "health_dim")
            for row in rows:
                status = (
                    "OK"
                    if row["found"] and row["returncode"] == 0
                    else "not found on PATH"
                )
                status_tag = "health_ok" if status == "OK" else "health_warn"
                if row["name"] == "pipx" and status == "not found on PATH":
                    status = (
                        "optional — uv covers this role" if "uv" in healthy_tools else "optional"
                    )
                    status_tag = "health_dim"
                if row["found"] and row["returncode"] != 0:
                    status = f"exit {row['returncode']}"
                    status_tag = "health_warn"
                if row.get("timed_out"):
                    status = "timed out"
                    status_tag = "health_error"
                executable = str(row.get("executable", "")).casefold()
                if status == "OK" and executable in path_report.recovered_tools:
                    status = "OK — recovered for this session"
                    status_tag = "health_warn"
                elif status == "OK" and executable in path_report.affected_tools:
                    status = "OK — saved PATH needs repair"
                    status_tag = "health_warn"
                text.insert("end", f"{row['name']}: ", "health_label")
                text.insert("end", f"{status}\n", status_tag)
                text.insert("end", "  purpose: ", "health_dim")
                text.insert("end", f"{row['description']}\n")
                text.insert("end", "  path: ", "health_dim")
                text.insert("end", f"{row['path'] or '(not found on PATH)'}\n", "health_path")
                text.insert("end", "  command: ", "health_dim")
                text.insert("end", f"{row['command']}\n", "health_command")
                text.insert("end", "  first line: ", "health_dim")
                text.insert("end", f"{row['first_line'] or '(none)'}\n\n")
            text.configure(state="disabled")
            if reason == "install":
                self._append_log("Toolchain health refreshed after the suggested install.")

        def start_scan(reason: str = "install") -> None:
            if not window.winfo_exists():
                return
            self._path_refresh_report = merge_windows_path_refresh_reports(
                self._path_refresh_report,
                refresh_process_path_from_windows_environment(),
            )
            path_report = self._path_refresh_report
            self._toolchain_health_generation += 1
            generation = self._toolchain_health_generation
            refresh_button.configure(state="disabled")
            text.configure(state="normal")
            text.delete("1.0", "end")
            text.insert(
                "1.0",
                "Refreshing developer toolchain paths and versions...\n",
                "health_title",
            )
            text.configure(state="disabled")
            threading.Thread(
                target=self._toolchain_health_worker,
                args=(
                    lambda rows: finish(rows, generation, reason, path_report),
                ),
                name="wdp-toolchain-health",
                daemon=True,
            ).start()

        def cleanup(event: Any) -> None:
            if event.widget is not window:
                return
            self._toolchain_health_generation += 1
            if self._toolchain_health_window is window:
                self._toolchain_health_window = None
                self._toolchain_health_refresh = None

        window.bind("<Destroy>", cleanup, add="+")
        self._toolchain_health_refresh = start_scan
        start_scan("open")

    def _toolchain_health_worker(self, callback: Any) -> None:
        def probe(name: str, description: str, command: tuple[str, ...]) -> dict[str, Any]:
            executable = command[0]
            path = shutil.which(executable) or ""
            if not path:
                return {
                    "name": name,
                    "description": description,
                    "executable": executable,
                    "found": False,
                    "path": "",
                    "command": subprocess.list2cmdline(list(command)),
                    "returncode": 127,
                    "duration_seconds": 0.0,
                    "timed_out": False,
                    "first_line": "",
                }
            result = run_capture(command, timeout=5)
            first_line = next(
                (line.strip() for line in result.output.splitlines() if line.strip()), ""
            )
            return {
                "name": name,
                "description": description,
                "executable": executable,
                "found": True,
                "path": path,
                "command": redact_sensitive_text(subprocess.list2cmdline(list(command))),
                "returncode": result.returncode,
                "duration_seconds": result.duration_seconds,
                "timed_out": result.timed_out,
                "first_line": first_line[:240],
            }

        rows: list[dict[str, Any]] = []
        with concurrent.futures.ThreadPoolExecutor(max_workers=6) as executor:
            futures = [
                executor.submit(probe, name, description, command)
                for name, description, command in TOOLCHAIN_PROBES
            ]
            rows.extend(future.result() for future in concurrent.futures.as_completed(futures))
        order = {
            name: index for index, (name, _description, _command) in enumerate(TOOLCHAIN_PROBES)
        }
        rows.sort(key=lambda row: order.get(str(row["name"]), 999))
        self.logger.event("toolchain_health_scan_finished", probes=rows)
        self.events.put(("ui_callback", (callback, (rows,))))

    def probe_selected_once(self) -> None:
        if self.busy:
            return
        selected = [
            item for item in self.items.values() if item.selected and self._item_is_actionable(item)
        ]
        portable_advisories = [
            item for item in selected if item.provider == PORTABLE_PROVIDER_KEY
        ]
        if portable_advisories:
            self._explain_manual_portable_updates(portable_advisories)
            selected = [
                item for item in selected if item.provider != PORTABLE_PROVIDER_KEY
            ]
        if not selected:
            if not portable_advisories:
                self._notify_user(
                    "Select at least one actionable package first.",
                    summary="Select an actionable package first",
                )
            return
        self._confirm_update_batch(selected, probe_once=True)

    def update_selected(self) -> None:
        if self.busy:
            return
        selected = [item for item in self.items.values() if item.selected]
        if not selected:
            self._notify_user("Select at least one update first.", summary="Select updates first")
            return
        needs_check = self._selected_winget_rows_needing_preflight(selected)
        if needs_check:
            self._start_selected_winget_preflight([item.key for item in selected], needs_check)
            return
        self._begin_update_request_feedback()
        self._continue_update_selected(selected)

    def _begin_update_request_feedback(self) -> None:
        """Acknowledge the click before preflight/confirmation, without delaying work."""
        self.cancel_requested.clear()
        self._hide_notification_banner()
        self._cancel_after_id("_update_request_cue_after_id")
        self._update_request_cue_until = time.monotonic() + UPDATE_REQUEST_CUE_MS / 1000
        self.progress.stop()
        self.progress.configure(mode="determinate")
        self._set_progress_value(0, animate=False)
        self._set_busy(True, "Checking selected updates — no installer started", kind="selected-preflight")
        self.summary_var.set("Checking selected updates — no installer started")
        # This only controls the cue's brief visibility. A refusal, confirmation,
        # update worker or scan can proceed immediately; none wait for this timer.
        self._update_request_cue_after_id = self.root.after(
            UPDATE_REQUEST_CUE_MS, self._finish_update_request_cue
        )

    def _finish_update_request_cue(self) -> None:
        self._update_request_cue_after_id = None
        self._update_request_cue_until = 0.0
        self._draw_update_progress_activity()

    def _continue_update_selected(self, selected: list[UpdateItem]) -> None:
        if self.busy and self._busy_kind == "selected-preflight":
            self._set_busy(False)
        portable_advisories = [
            item for item in selected if item.provider == PORTABLE_PROVIDER_KEY
        ]
        if portable_advisories:
            self._explain_manual_portable_updates(portable_advisories)
            selected = [
                item for item in selected if item.provider != PORTABLE_PROVIDER_KEY
            ]
            if not selected:
                return
        ordinary_selected = [item for item in selected if self._item_is_bulk_selectable(item)]
        review_items = [item for item in selected if not self._item_is_bulk_selectable(item)]
        if review_items and not ordinary_selected:
            names = "\n".join(f"- {item.name}: {item.status}" for item in review_items[:8])
            if len(review_items) > 8:
                names += f"\n- ... {len(review_items) - 8} more"
            summary = (
                f"No update started — {review_items[0].name}: {review_items[0].status}"
                if len(review_items) == 1
                else f"No updates started — {len(review_items)} selected packages need review"
            )
            self._notify_user(
                "No installer was started. Normal Update only runs packages predicted "
                "to be ordinary updates.\n\n"
                "All selected packages need review or are predicted not to update here:\n\n"
                f"{names}\n\n"
                "Double-click the package for Details. After reviewing the cause, "
                "keep it checked and choose the sprocket menu > Test once if you "
                "deliberately want one diagnostic retry; it still asks for confirmation.",
                level="warning",
                summary=summary,
            )
            self._show_notification_banner(
                "No update started. Double-click for Details; sprocket > Test once offers a confirmed retry.",
                level="warning",
            )
            self.logger.event(
                "update_request_not_started", reason="selected-packages-need-review",
                item_count=len(review_items), candidate_keys=[item.candidate_key for item in review_items],
            )
            return
        if review_items:
            names = "\n".join(f"- {item.name}: {item.status}" for item in review_items[:8])
            if len(review_items) > 8:
                names += f"\n- ... {len(review_items) - 8} more"
            if not self.messagebox.askokcancel(
                "Confirm ordinary updates",
                f"Normal Update will run {len(ordinary_selected)} ordinary package(s).\n\n"
                f"{len(review_items)} selected review package(s) will be left untouched:\n\n"
                f"{names}\n\n"
                "Use Test once separately if you want diagnostic attempts for those packages.",
            ):
                return
        self._confirm_update_batch(ordinary_selected, probe_once=False)

    def _explain_manual_portable_updates(
        self,
        items: Sequence[UpdateItem],
    ) -> None:
        names = ", ".join(item.name for item in items[:4])
        if len(items) > 4:
            names += f", and {len(items) - 4} more"
        self._append_log(
            f"Portable update kept manual: {names}. Provider installation was not started."
        )
        self.logger.event(
            "portable_updates_refused",
            count=len(items),
            items=[item_diagnostic_fields(item) for item in items],
            reason="preserve-user-selected-portable-layout",
        )
        self._notify_user(
            (
                f"{len(items)} selected portable update(s) were left untouched. "
                "WinDevPilot found newer catalog releases, but installing their provider "
                "packages could convert deliberately portable copies into registered installs. "
                "Use Package Details for the official homepage or WinGet installer reference, "
                "then replace the portable files manually."
            ),
            level="warning",
            summary="Portable updates remain manual",
        )

    def _selected_winget_rows_needing_preflight(
        self, selected: Sequence[UpdateItem]
    ) -> list[UpdateItem]:
        if not isinstance(self.providers.get(WingetProvider.key), WingetProvider):
            return []
        holds = self.settings.data.get("attempt_holds", {})
        return [
            item
            for item in selected
            if item.provider == WingetProvider.key
            and item.applicability_prediction in {PREDICTION_PENDING, PREDICTION_UNKNOWN}
            and item.classification in {CLASS_SIMPLE_UPGRADE, CLASS_MANUAL_REVIEW}
            and not (
                isinstance(holds, dict)
                and isinstance((hold := holds.get(item.candidate_key)), dict)
                and attempt_record_matches_current_strategy(hold)
            )
        ]

    def _start_selected_winget_preflight(
        self, selected_keys: list[str], needs_check: list[UpdateItem]
    ) -> None:
        provider = self.providers.get(WingetProvider.key)
        if not isinstance(provider, WingetProvider):
            update_items = self._scan_view_items[False]
            self._continue_update_selected(
                [update_items[key] for key in selected_keys if key in update_items]
            )
            return
        self._append_log(
            f"Checking WinGet details for {len(needs_check)} selected package(s) before update"
        )
        self._begin_update_request_feedback()
        snapshots = [dataclasses.replace(item) for item in needs_check]

        def enrich(snapshot: UpdateItem) -> UpdateItem:
            try:
                with self._provider_operation_locks[WingetProvider.key]:
                    return provider.preflight_item(snapshot)
            except Exception as exc:
                return set_applicability_prediction(
                    snapshot,
                    PREDICTION_UNKNOWN,
                    confidence="low",
                    source="selected-winget-show",
                    reasons=[f"selected WinGet manifest check failed: {type(exc).__name__}: {exc}"],
                    classification=CLASS_MANUAL_REVIEW,
                    status="Review - manifest unavailable",
                )

        def worker() -> None:
            max_workers = min(3, len(snapshots))
            with concurrent.futures.ThreadPoolExecutor(max_workers=max_workers) as executor:
                enriched = list(executor.map(enrich, snapshots))
            self.events.put(("selected_preflight_done", (selected_keys, enriched)))

        self._start_guarded_worker(
            worker,
            name="wdp-selected-preflight",
            operation="selected-preflight",
        )

    def _finish_selected_winget_preflight(
        self, selected_keys: list[str], enriched: list[UpdateItem]
    ) -> None:
        self._set_busy(False)
        update_items = self._scan_view_items[False]
        for row in enriched:
            row.selected = True
            self._item_icon_source_cache.pop(row.key, None)
            update_items[row.key] = row
            if not self._last_scan_all_packages:
                self._refresh_item_row(row)
        if not self._last_scan_all_packages:
            self._refresh_scan_summary_counts()
        if self.cancel_requested.is_set():
            self._append_log(
                "Stop requested during WinGet detail checks; the update confirmation was cancelled"
            )
            self.summary_var.set("No update started — cancelled during the checks")
            return
        selected = [
            update_items[key]
            for key in selected_keys
            if key in update_items and update_items[key].selected
        ]
        if not selected:
            self._notify_user(
                "No selected updates remain after the WinGet detail checks.",
                summary="Select updates first",
            )
            return
        self._continue_update_selected(selected)

    def _confirm_update_batch(self, selected: list[UpdateItem], *, probe_once: bool) -> None:
        admin_items = [item for item in selected if item.requires_admin]
        review_items = [item for item in selected if not self._item_is_bulk_selectable(item)]
        attempt_holds = self.settings.data.get("attempt_holds", {})
        held_overrides = [
            item for item in selected if isinstance(attempt_holds.get(item.candidate_key), dict)
        ]
        predicted_failures = [
            item
            for item in selected
            if item.applicability_prediction not in {"", PREDICTION_ORDINARY, PREDICTION_UNKNOWN}
        ]
        if (
            admin_items
            and not self.process_is_admin
            and not self.settings.data.get("auto_elevate", True)
        ):
            self._notify_user(
                "Some selected updates need administrator rights. Enable the one-prompt "
                "elevation option in Providers, or deselect those packages.",
                level="warning",
                summary="Machine updates need elevation option enabled",
            )
            return
        verb = "Test" if probe_once else "Update"
        kind_text = (
            "This is a one-off diagnostic test. It is allowed to fail and is not "
            "treated as evidence that repeated retries will help."
            if probe_once
            else "Only ordinary predicted updates are included."
        )
        if not admin_items:
            machine_execution = "No selected updates require machine-scope privileges."
        elif self.process_is_admin:
            machine_execution = (
                f"{len(admin_items)} machine update(s) will run directly in this "
                "administrator process."
            )
        elif self.token_elevation_type == "limited":
            machine_execution = (
                f"{len(admin_items)} machine update(s) will share one UAC consent prompt "
                "in this administrator account."
            )
        else:
            machine_execution = (
                f"{len(admin_items)} machine update(s) will share one UAC consent or "
                "credential prompt."
            )
        message = (
            f"{verb} {len(selected)} selected package(s) silently?\n\n"
            f"{len(selected) - len(admin_items)} will run in the current account context.\n"
            f"{machine_execution}\n\n"
            f"{kind_text}\n\nWinDevPilot does not request a restart, but a vendor "
            "installer can still require or initiate one. Save active work before continuing."
        )
        if review_items:
            message += (
                f"\n\n{len(review_items)} selected package(s) carry a scope, identity, or "
                "prior-result safety hold. Review the Status column before continuing."
            )
        if predicted_failures:
            examples = "\n".join(
                f"- {item.name}: expected {item.predicted_hresult or item.applicability_prediction}"
                for item in predicted_failures[:6]
            )
            if len(predicted_failures) > 6:
                examples += f"\n- ... {len(predicted_failures) - 6} more"
            message += (
                "\n\nPredicted not to update normally:\n"
                f"{examples}\n\n"
                "Continue only if you want diagnostic evidence from one attempt."
            )
        if held_overrides:
            message += (
                f"\n\n{len(held_overrides)} exact candidate(s) were already held after a "
                "prior result. This confirmation is a one-attempt manual override."
            )
        reboot_reasons = pending_reboot_reasons() if admin_items else []
        if reboot_reasons:
            message += (
                "\n\nA Windows restart is already pending ("
                + ", ".join(reboot_reasons)
                + "). Restarting first usually improves the reliability of "
                "machine-level installers; you may still continue."
            )
        if not self.messagebox.askokcancel("Confirm updates", message):
            return
        self._retryable_failure_candidate_keys.clear()
        self._pending_retry_selection_candidate_keys.clear()
        self.active_update_id = uuid.uuid4().hex
        self.active_attempt_kind = "probe" if probe_once else "update"
        try:
            self.logger.write(
                f"Confirmed update batch {self.active_update_id}: "
                f"{len(selected)} selected package(s)"
            )
            self.logger.event(
                "update_batch_confirmed",
                update_id=self.active_update_id,
                attempt_kind=self.active_attempt_kind,
                item_count=len(selected),
                current_user_count=len(selected) - len(admin_items),
                privileged_count=len(admin_items),
                process_is_admin=self.process_is_admin,
                elevation_type=self.token_elevation_type,
                pending_reboot_reasons=reboot_reasons,
                predicted_failure_count=len(predicted_failures),
                attempt_hold_override_count=len(held_overrides),
                attempt_hold_override_candidate_keys=[
                    item.candidate_key for item in held_overrides
                ],
                items=[item_diagnostic_fields(item) for item in selected],
            )
        except OSError as exc:
            self.active_update_id = ""
            self.messagebox.showerror(
                APP_NAME,
                "The diagnostic logs are not writable, so no package operation was "
                f"started.\n\n{exc}",
            )
            return
        self.cancel_requested.clear()
        _RECENT_WINGET_INVENTORY.invalidate()
        self._mark_scan_refresh_needed(
            "A package operation may have changed installed versions; run a full scan to refresh"
        )
        self._active_operation_original_statuses = {
            item.key: item.status for item in selected
        }
        self._active_operation_results = []
        self._active_operation_items = {
            item.key: dataclasses.replace(item, status="Queued")
            for item in selected
        }
        self._confirmed_attempt_items = {
            key: dataclasses.replace(item) for key, item in self._active_operation_items.items()
        }
        self._update_progress_completed_keys.clear()
        for item in selected:
            self._set_scan_view_item_status(item.key, "Queued")
        self._set_busy(
            True,
            f"Updating {len(selected)} selected package(s)",
            kind="update",
        )
        self.progress.configure(mode="determinate")
        self._set_progress_value(0, animate=False)
        self.summary_var.set("Updating selected packages…")
        self._start_guarded_worker(
            lambda: self._update_worker(list(self._confirmed_attempt_items.values())),
            name="wdp-update",
            operation="update",
        )

    def _update_worker(self, selected: list[UpdateItem]) -> None:
        # A queue insertion is not proof of writable logs. Wait off Tk's thread
        # for the confirmation records before any provider command or elevation.
        if not self.logger.flush(timeout=5.0):
            raise RuntimeError("Diagnostic logs could not be flushed; no package operation started")
        normal = [item for item in selected if not item.requires_admin]
        privileged = [item for item in selected if item.requires_admin]
        total = len(selected)
        completed = 0
        results: list[dict[str, Any]] = []
        npm_global_root: Path | None = None
        installed_version_checks = WingetInstalledVersionChecks()

        def record_result(entry: dict[str, Any]) -> None:
            results.append(entry)
            # Publish an immutable snapshot only after a complete result exists.
            # The Tk failure path reads it after this worker has terminated.
            self._active_operation_results = list(results)

        if privileged and not self.cancel_requested.is_set():
            privileged, rejected = partition_elevated_candidates(privileged, self.providers)
            for item, entry in rejected:
                completed += 1
                record_result(entry)
                self.logger.event("update_item_not_started", update_id=self.active_update_id,
                                  item=item_diagnostic_fields(item), result=entry)
                self.events.put(("command_result", command_result_event_payload(item, entry)))

        def update_with_heartbeat(item: UpdateItem, provider: Provider) -> CommandResult:
            finished = threading.Event()

            def heartbeat() -> None:
                elapsed = 30
                while not finished.wait(30 if elapsed == 30 else 60):
                    self.events.put(
                        (
                            "operation_heartbeat",
                            (self.active_update_id, item.key, item.name, elapsed),
                        )
                    )
                    elapsed += 60

            threading.Thread(
                target=heartbeat,
                name=f"wdp-update-heartbeat-{item.provider}",
                daemon=True,
            ).start()
            try:
                return provider.update(item)
            finally:
                finished.set()

        for provider_key in sorted({item.provider for item in [*normal, *privileged]}):
            if self.cancel_requested.is_set():
                break
            provider = self.providers[provider_key]
            with self._provider_operation_locks[provider_key]:
                if self.cancel_requested.is_set():
                    break
                version_result = run_capture(provider.version_command(), timeout=60)
            self.logger.event(
                "provider_runtime",
                update_id=self.active_update_id,
                provider={
                    "key": provider.key,
                    "label": provider.label,
                    "configured_executable": provider.executable,
                    "resolved_executable": shutil.which(provider.executable),
                },
                version_probe=command_diagnostic_fields(version_result),
            )

        for item in normal:
            if self.cancel_requested.is_set():
                break
            completed += 1
            self.events.put(("item_status", (item.key, "Updating…", completed, total)))
            self.events.put(("log", f"[{completed}/{total}] Updating {item.name} as current user"))
            if self.active_attempt_kind == "probe":
                self.logger.event(
                    "probe_attempt",
                    update_id=self.active_update_id,
                    item=item_diagnostic_fields(item),
                    expected_code=item.predicted_hresult,
                    predicted_outcome=item.applicability_prediction,
                )
            self.logger.event(
                "update_item_start",
                update_id=self.active_update_id,
                attempt_kind=self.active_attempt_kind,
                sequence=completed,
                total=total,
                execution_context="current-user",
                item=item_diagnostic_fields(item),
            )
            provider = self.providers[item.provider]
            with self._provider_operation_locks[item.provider]:
                result = update_with_heartbeat(item, provider)
            self.events.put(("item_status", (
                item.key, "Command finished; collecting evidence…", completed, total,
            )))
            entry = command_result_entry(
                item,
                provider,
                result,
                execution_context="current-user",
            )
            if item.provider == NpmProvider.key and entry.get("success"):
                postcheck, npm_global_root = npm_post_update_integrity(
                    item, npm_global_root
                )
                entry["npm_postcheck"] = postcheck
                postcheck_warnings: list[str] = []
                if postcheck.get("error"):
                    postcheck_warnings.append(
                        "npm structural post-check was inconclusive: "
                        f"{postcheck['error']}"
                    )
                elif not postcheck.get("version_matches"):
                    postcheck_warnings.append(
                        "npm installed manifest version did not match the requested target"
                    )
                missing_commands = [
                    str(value)
                    for value in postcheck.get("missing_command_targets", [])
                    if value
                ]
                if missing_commands:
                    postcheck_warnings.append(
                        f"npm package is missing {len(missing_commands)} declared command "
                        f"target(s): {', '.join(missing_commands[:3])}"
                    )
                if postcheck_warnings:
                    entry["warnings"] = list(
                        dict.fromkeys(
                            [
                                *[str(value) for value in entry.get("warnings", [])],
                                *postcheck_warnings,
                            ]
                        )
                    )
                if entry.get("warnings"):
                    entry["outcome"] = "updated-with-warnings"
                    entry["status_hint"] = "Updated with warnings"
            if entry.get("success") and not entry.get("needs_reboot"):
                self.events.put(("item_status", (
                    item.key, "Checking installed version…", completed, total,
                )))
            with self._provider_operation_locks[item.provider]:
                installed_version_checks.check(item, entry)
            record_result(entry)
            self.logger.event(
                "update_item_result",
                update_id=self.active_update_id,
                item=item_diagnostic_fields(item),
                result=entry,
            )
            self.events.put(("command_result", command_result_event_payload(item, entry)))

        if privileged and not self.cancel_requested.is_set():
            for offset, item in enumerate(privileged, start=1):
                self.events.put(
                    (
                        "item_status",
                        (item.key, "Queued for administrator", completed + offset, total),
                    )
                )
                if self.active_attempt_kind == "probe":
                    self.logger.event(
                        "probe_attempt",
                        update_id=self.active_update_id,
                        item=item_diagnostic_fields(item),
                        expected_code=item.predicted_hresult,
                        predicted_outcome=item.applicability_prediction,
                    )
            privileged_start_message = (
                f"Running {len(privileged)} machine update(s) directly in the current "
                "administrator process…"
                if self.process_is_admin
                else f"Requesting one UAC prompt for {len(privileged)} machine update(s)…"
            )
            self.events.put(("log", privileged_start_message))
            self.logger.event(
                "elevation_batch_start",
                update_id=self.active_update_id,
                attempt_kind=self.active_attempt_kind,
                item_count=len(privileged),
                process_is_already_admin=self.process_is_admin,
                elevation_type=self.token_elevation_type,
                items=[item_diagnostic_fields(item) for item in privileged],
            )
            elevated_base_completed = completed
            streamed_result_keys: set[str] = set()
            elevated_execution_context = (
                "already-elevated-process" if self.process_is_admin else "elevated-helper"
            )

            def publish_elevated_progress(
                kind: str,
                item: UpdateItem,
                entry: dict[str, Any] | None,
                sequence: int,
                _privileged_total: int,
                elapsed_seconds: int,
            ) -> None:
                nonlocal completed
                overall_sequence = elevated_base_completed + sequence
                if kind == "item_start":
                    self.events.put(
                        (
                            "item_status",
                            (item.key, "Updating as administrator…", overall_sequence, total),
                        )
                    )
                    self.events.put(
                        (
                            "log",
                            f"[{overall_sequence}/{total}] Updating {item.name} as administrator",
                        )
                    )
                    self.logger.event(
                        "update_item_start",
                        update_id=self.active_update_id,
                        attempt_kind=self.active_attempt_kind,
                        sequence=overall_sequence,
                        total=total,
                        execution_context=elevated_execution_context,
                        item=item_diagnostic_fields(item),
                    )
                    return
                if kind == "heartbeat":
                    self.events.put(
                        (
                            "operation_heartbeat",
                            (
                                self.active_update_id,
                                item.key,
                                item.name,
                                elapsed_seconds,
                            ),
                        )
                    )
                    return
                if kind != "item_result" or entry is None or item.key in streamed_result_keys:
                    return
                streamed_result_keys.add(item.key)
                completed += 1
                record_result(entry)
                self.logger.event(
                    "update_item_result",
                    update_id=self.active_update_id,
                    item=item_diagnostic_fields(item),
                    result=entry,
                )
                self.events.put(
                    (
                        "item_status",
                        (item.key, operation_result_status(entry), completed, total),
                    )
                )
                self.events.put(("command_result", command_result_event_payload(item, entry)))

            self._elevated_batch_inflight = True
            try:
                with contextlib.ExitStack() as provider_locks:
                    for provider_key in sorted({item.provider for item in privileged}):
                        provider_locks.enter_context(
                            self._provider_operation_locks[provider_key]
                        )
                    if self.process_is_admin:
                        revalidation_failures = revalidate_elevated_targets(privileged)
                        elevated_results = execute_items_direct(
                            privileged,
                            self.providers,
                            execution_context="already-elevated-process",
                            precomputed_results=revalidation_failures,
                            on_item_start=lambda item, sequence, batch_total: (
                                publish_elevated_progress(
                                    "item_start", item, None, sequence, batch_total, 0
                                )
                            ),
                            on_item_result=lambda item, entry, sequence, batch_total: (
                                publish_elevated_progress(
                                    "item_result", item, entry, sequence, batch_total, 0
                                )
                            ),
                        )
                    else:
                        elevated_results = execute_elevated_batch(
                            privileged,
                            progress_callback=publish_elevated_progress,
                        )
                by_key = {entry["key"]: entry for entry in elevated_results}
                for item in privileged:
                    if item.key in streamed_result_keys:
                        continue
                    completed += 1
                    entry = by_key.get(
                        item.key,
                        diagnostic_failure_entry(
                            item,
                            "missing elevated result",
                            execution_context="elevated-helper",
                        ),
                    )
                    record_result(entry)
                    self.logger.event(
                        "update_item_result",
                        update_id=self.active_update_id,
                        item=item_diagnostic_fields(item),
                        result=entry,
                    )
                    self.events.put(
                        (
                            "item_status",
                            (
                                item.key,
                                operation_result_status(entry),
                                completed,
                                total,
                            ),
                        )
                    )
                    self.events.put(("command_result", command_result_event_payload(item, entry)))
            except ElevationCancelled as exc:
                message = str(exc)
                self.events.put(("log", message))
                for item in privileged:
                    if item.key in streamed_result_keys:
                        continue
                    completed += 1
                    entry = diagnostic_failure_entry(
                        item,
                        message,
                        execution_context="uac-launch",
                        returncode=ERROR_CANCELLED,
                        cancelled=True,
                    )
                    record_result(entry)
                    self.logger.event(
                        "update_item_result",
                        update_id=self.active_update_id,
                        item=item_diagnostic_fields(item),
                        result=entry,
                    )
                    self.events.put(("item_status", (item.key, "Cancelled", completed, total)))
                    self.events.put(("command_result", command_result_event_payload(item, entry)))
            except Exception as exc:
                error = f"Elevation failed: {exc}"
                self.events.put(("log", error))
                for item in privileged:
                    if item.key in streamed_result_keys:
                        continue
                    completed += 1
                    entry = diagnostic_failure_entry(
                        item,
                        error,
                        execution_context="elevation-launch-or-receipt",
                    )
                    record_result(entry)
                    self.logger.event(
                        "update_item_result",
                        update_id=self.active_update_id,
                        item=item_diagnostic_fields(item),
                        result=entry,
                    )
                    self.events.put(("item_status", (item.key, "Failed", completed, total)))
                    self.events.put(("command_result", command_result_event_payload(item, entry)))
            self._elevated_batch_inflight = False
        self.events.put(("update_done", (results, total)))

    def _show_command_result(
        self, item: UpdateItem, entry: dict[str, Any], ui_output: str | None = None
    ) -> None:
        success = bool(entry.get("success"))
        warnings = [str(value) for value in entry.get("warnings", []) if value]
        hint = str(entry.get("status_hint", "")).strip()
        status = (
            provisional_operation_result_status(entry)
            if success and self.active_attempt_kind in {"update", "probe"}
            else operation_result_status(entry)
        )
        item.status = status
        self._set_scan_view_item_status(item.key, status)
        if proof := entry.get("installed_version_check"):
            self._append_log(
                f"{item.name}: installed-version check {proof.get('status', 'inconclusive')}"
                f" ({proof.get('elapsed_seconds', 0)}s); final provider scan still follows."
            )
        command = str(entry.get("command", ""))
        if command:
            self._append_log(
                f"Command: {command}",
                already_redacted=True,
                show_in_ui=False,
            )
        self._append_log(
            "Process: "
            f"context={entry.get('execution_context', '?')} "
            f"pid={entry.get('process_id', '?')} "
            f"started={wall_clock_display_timestamp(entry.get('started_at', '?'))} "
            f"finished={wall_clock_display_timestamp(entry.get('finished_at', '?'))} "
            f"duration={entry.get('duration_seconds', '?')}s "
            f"exit={entry.get('returncode', '?')} "
            f"normalized={entry.get('returncode_hex', '?')} "
            f"timed_out={bool(entry.get('timed_out'))}",
            show_in_ui=False,
        )
        output = str(entry.get("output", "")).strip()
        if output:
            self._append_log(output, already_redacted=True, show_in_ui=False)
            if ui_output is None:
                ui_output = compact_process_output_for_ui(
                    output,
                    provider_key=item.provider,
                )
            if ui_output:
                self._append_log(
                    ui_output,
                    already_redacted=True,
                    persist=False,
                )
        if entry.get("capture_truncated") or not entry.get("capture_complete", True):
            self._append_log(
                "Process output capture was incomplete: "
                f"observed bytes={entry.get('capture_bytes', '?')}, "
                f"native exit={entry.get('process_returncode', '?')}. "
                "The stored output and its SHA-256 cover only the retained excerpt; "
                "verify installed state before retrying.",
                show_in_ui=False,
            )
        if entry.get("output_truncated"):
            self._append_log(
                "Output was bounded for safe sharing: "
                f"{entry.get('output_chars', '?')} redacted chars total, "
                f"{entry.get('output_omitted_chars', '?')} omitted, "
                f"SHA-256={entry.get('output_redacted_sha256', '?')}",
                show_in_ui=False,
            )
        for related_log in entry.get("related_installer_logs", []):
            path = str(related_log.get("path", "WinGet child installer log"))
            self._append_log(
                f"Related installer log: {path} "
                f"({related_log.get('size_bytes', '?')} bytes, "
                f"SHA-256={related_log.get('file_sha256', '?')})",
                show_in_ui=False,
            )
            related_output = str(related_log.get("output", "")).strip()
            if related_output:
                self._append_log(
                    related_output,
                    already_redacted=True,
                    show_in_ui=False,
                )
            read_error = str(related_log.get("read_error", "")).strip()
            if read_error:
                self._append_log(
                    f"Could not capture related installer log: {read_error}",
                    show_in_ui=False,
                )
            if related_log.get("output_truncated") or related_log.get("read_omitted_bytes"):
                self._append_log(
                    "Related installer log was bounded for safe sharing: "
                    f"{related_log.get('output_chars', '?')} redacted chars, "
                    f"{related_log.get('output_omitted_chars', 0)} chars omitted, "
                    f"{related_log.get('read_omitted_bytes', 0)} source bytes omitted",
                    show_in_ui=False,
                )
        error = str(entry.get("error", "")).strip()
        if error:
            self._append_log(error)
        for warning in warnings:
            self._append_log(f"Warning: {warning}")
        blocker_advice = file_blocker_guidance(entry.get("file_blockers", {}))
        if blocker_advice:
            self._append_log(f"Guidance: {blocker_advice}")
        npm_postcheck = entry.get("npm_postcheck", {})
        if isinstance(npm_postcheck, dict) and npm_postcheck:
            if npm_postcheck.get("error"):
                postcheck_summary = "inconclusive; see the warning above"
            else:
                present = len(npm_postcheck.get("present_command_targets", []))
                missing = len(npm_postcheck.get("missing_command_targets", []))
                version_state = (
                    "target version installed"
                    if npm_postcheck.get("version_matches")
                    else "target version mismatch"
                )
                command_state = (
                    f"; {present} declared command target(s) present"
                    if present
                    else ""
                )
                if missing:
                    command_state += f"; {missing} missing"
                postcheck_summary = f"{version_state}{command_state}"
            self._append_log(
                f"npm structural post-check: {postcheck_summary}"
            )
        pip_effects = entry.get("pip_side_effects", {})
        if isinstance(pip_effects, dict) and pip_effects:
            touched = [str(value) for value in pip_effects.get("touched_packages", []) if value]
            dependencies = [
                value for value in touched if value.casefold() != item.package_id.casefold()
            ]
            conflicts = [str(value) for value in pip_effects.get("resolver_conflicts", []) if value]
            scripts = [str(value) for value in pip_effects.get("scripts_not_on_path", []) if value]
            installed = pip_effects.get("successfully_installed", {})
            installed_count = len(installed) if isinstance(installed, dict) else 0
            if touched or conflicts or scripts or installed_count:
                self._append_log(
                    "pip side effects: "
                    f"{installed_count} package(s) installed/upgraded; "
                    f"{compact_list_summary(dependencies, singular='dependency touched', plural='dependencies touched')}; "
                    f"{compact_list_summary(conflicts, singular='dependency warning line', plural='dependency warning lines')}; "
                    f"{compact_list_summary(scripts, singular='PATH warning', plural='PATH warnings')}"
                )
                if len(dependencies) > 3 or len(conflicts) > 3 or len(scripts) > 3:
                    self._append_log(compact_pip_detail_hint(item.package_id))
        if hint and not success:
            self._append_log(f"Guidance: {hint}")
        attempted_item = (
            getattr(self, "_confirmed_attempt_items", {}).get(item.key) or item
        )
        if explanation := winget_not_applicable_explanation(attempted_item, entry):
            self._append_log(explanation)
        self._append_log(f"{item.name}: {item.status} (exit {entry.get('returncode', '?')})")

    def _remember_attempt_outcomes(self, results: Sequence[dict[str, Any]]) -> None:
        original_holds = dict(self.settings.data.get("attempt_holds", {}))
        holds = dict(original_holds)
        original_restart_pending = dict(
            self.settings.data.get("restart_pending", {})
        )
        restart_pending = dict(original_restart_pending)
        original_history = dict(self.settings.data.get("applicability_history", {}))
        history = dict(original_history)
        added: list[str] = []
        removed: list[str] = []
        restart_added: list[str] = []
        restart_removed: list[str] = []
        history_updated: list[str] = []
        history_removed: list[str] = []
        update_items = self._scan_view_items[False]
        for entry in results:
            key = str(entry.get("key", ""))
            if entry.get("execution_context") == "local-plan-validation":
                # No package command ran; do not learn installer failure policy.
                continue
            item = (getattr(self, "_confirmed_attempt_items", {}).get(key)
                    or getattr(self, "_active_operation_items", {}).get(key) or update_items.get(key))
            if item is None:
                continue
            candidate_key = item.candidate_key
            identity_key = item.verification_identity_key
            history_key = applicability_history_key(item)
            if entry.get("success"):
                if holds.pop(candidate_key, None) is not None:
                    removed.append(candidate_key)
                if history.pop(history_key, None) is not None:
                    history_removed.append(history_key)
                if entry.get("needs_reboot"):
                    restart_pending[identity_key] = build_restart_pending_marker(
                        item, entry
                    )
                    restart_added.append(identity_key)
                elif restart_pending.pop(identity_key, None) is not None:
                    restart_removed.append(identity_key)
                continue
            outcome = str(entry.get("outcome", ""))
            if entry.get("cancelled") or outcome not in {
                "failed",
                "not-applicable",
                "verification-conflict",
                "verification-state-change",
            }:
                continue
            prior = holds.get(candidate_key)
            holds[candidate_key] = build_attempt_hold_record(
                item,
                entry,
                prior if isinstance(prior, dict) else None,
            )
            added.append(candidate_key)
            if (
                item.provider == WingetProvider.key
                and attempt_hold_classification(entry) == CLASS_SCOPE_OR_APPLICABILITY
            ):
                prior_history = history.get(history_key)
                try:
                    prior_history_count = (
                        int(prior_history.get("count", 0))
                        if attempt_record_matches_current_strategy(prior_history)
                        else 0
                    )
                except (TypeError, ValueError):
                    prior_history_count = 0
                prior_exact_count = 0
                for held_record in original_holds.values():
                    if (
                        isinstance(held_record, dict)
                        and attempt_record_matches_current_strategy(held_record)
                        and applicability_history_key_from_diagnostic(
                            held_record.get("item")
                        )
                        == history_key
                        and attempt_hold_classification(held_record)
                        == CLASS_SCOPE_OR_APPLICABILITY
                    ):
                        try:
                            prior_exact_count += max(1, int(held_record.get("count", 1)))
                        except (TypeError, ValueError):
                            prior_exact_count += 1
                observed_at = str(entry.get("finished_at") or utc_now_iso())
                previous_candidates = (
                    [
                        str(value)
                        for value in prior_history.get("candidate_keys", [])
                        if isinstance(value, str) and SHA256_RE.fullmatch(value)
                    ]
                    if isinstance(prior_history, dict)
                    else []
                )
                history[history_key] = {
                    "schema": 1,
                    "strategy_revision": WINGET_ATTEMPT_STRATEGY_REVISION,
                    "first_seen": (
                        str(prior_history.get("first_seen", observed_at))
                        if isinstance(prior_history, dict)
                        else observed_at
                    ),
                    "last_seen": observed_at,
                    "count": max(prior_history_count, prior_exact_count) + 1,
                    "outcome": outcome,
                    "returncode_hex": str(entry.get("returncode_hex", "")),
                    "classification": CLASS_SCOPE_OR_APPLICABILITY,
                    "status_hint": str(entry.get("status_hint", "")),
                    "candidate_keys": list(
                        dict.fromkeys([*previous_candidates, candidate_key])
                    )[-12:],
                    "item": item_diagnostic_fields(item),
                }
                history_updated.append(history_key)
        ordered_holds = sorted(
            holds.items(),
            key=lambda pair: wall_clock_order_key(
                pair[1].get("last_seen", pair[1].get("attempted_at", ""))
            ),
            reverse=True,
        )[:MAX_ATTEMPT_HOLDS]
        trimmed_holds = dict(ordered_holds)
        ordered_restart_pending = dict(
            sorted(
                restart_pending.items(),
                key=lambda pair: wall_clock_order_key(pair[1].get("attempted_at", "")),
                reverse=True,
            )[:MAX_RESTART_PENDING_MARKERS]
        )
        recent_history = {
            key: record
            for key, record in history.items()
            if applicability_history_is_recent(record)
        }
        ordered_history = dict(
            sorted(
                recent_history.items(),
                key=lambda pair: wall_clock_order_key(pair[1].get("last_seen", "")),
                reverse=True,
            )[:MAX_APPLICABILITY_HISTORY]
        )
        if (
            trimmed_holds == original_holds
            and ordered_restart_pending == original_restart_pending
            and ordered_history == original_history
        ):
            return
        self.settings.data["attempt_holds"] = trimmed_holds
        self.settings.data["restart_pending"] = ordered_restart_pending
        self.settings.data["applicability_history"] = ordered_history
        try:
            self.settings.save()
            self.logger.event(
                "attempt_holds_updated",
                update_id=self.active_update_id,
                held_count=len(trimmed_holds),
                added_candidate_keys=added,
                removed_candidate_keys=removed,
                held_classifications={
                    key: str(trimmed_holds[key].get("classification", ""))
                    for key in added
                    if key in trimmed_holds
                },
            )
            if history_updated or history_removed:
                self.logger.event(
                    "applicability_history_updated",
                    update_id=self.active_update_id,
                    remembered_keys=sorted(set(history_updated)),
                    removed_after_success=sorted(set(history_removed)),
                    remembered_count=len(ordered_history),
                )
            if restart_added or restart_removed:
                self.logger.event(
                    "restart_pending_updated",
                    update_id=self.active_update_id,
                    remembered_identity_keys=sorted(set(restart_added)),
                    removed_after_non_reboot_success=sorted(set(restart_removed)),
                    remembered_count=len(ordered_restart_pending),
                )
        except OSError as exc:
            self.settings.data["attempt_holds"] = original_holds
            self.settings.data["restart_pending"] = original_restart_pending
            self.settings.data["applicability_history"] = original_history
            self._append_log(f"Could not save attempt safety holds: {exc}")

    def _finish_update(self, results: list[dict[str, Any]], total: int) -> None:
        self._elevated_batch_inflight = False
        self._remember_attempt_outcomes(results)
        attempt_items = {**self._scan_view_items[False], **self._active_operation_items,
                         **getattr(self, "_confirmed_attempt_items", {})}
        self._retryable_failure_candidate_keys = retryable_failure_candidate_keys(
            results, attempt_items
        )
        self._active_operation_original_statuses.clear()
        completed_keys = {str(entry.get("key", "")) for entry in results}
        for key in self._active_operation_items.keys() - completed_keys:
            self._active_operation_items[key].selected = False
            for catalog in self._scan_view_items.values():
                if key in catalog:
                    catalog[key].selected = False
            self._set_scan_view_item_status(key, "Skipped after stop request")
        counts = update_result_counts(results, total)
        succeeded = counts["successful"]
        updated = counts["updated"]
        already_current = counts["already_current"]
        not_applicable = counts["not_applicable"]
        with_warnings = counts["with_warnings"]
        failed = counts["failed"]
        cancelled = counts["cancelled"]
        skipped = counts["skipped"]
        reboot_required = counts["reboot_required"]
        if succeeded:
            invalidate_start_menu_shortcut_index()
        self._set_progress_value(100 if results else 0)
        summary_body = nonzero_count_summary(
            (
                ("updated", updated),
                ("already current", already_current),
                ("not applicable", not_applicable),
                ("failed", failed),
                ("cancelled", cancelled),
                ("skipped", skipped),
                ("with warnings", with_warnings),
                ("need restart", reboot_required),
            ),
            zero_message="no package changes reported",
        )
        summary = f"Finished: {summary_body}"
        self.summary_var.set(summary)
        self._append_log(f"Update run finished: {summary_body}")
        self._append_log(f"LLM diagnostic trace saved: {self.logger.trace_path}")
        self.logger.event(
            "update_batch_finished",
            update_id=self.active_update_id,
            total=total,
            succeeded=succeeded,
            updated=updated,
            already_current=already_current,
            not_applicable=not_applicable,
            with_warnings=with_warnings,
            failed=failed,
            cancelled=cancelled,
            skipped=skipped,
            reboot_required=reboot_required,
            stop_requested=self.cancel_requested.is_set(),
            human_log=self.logger.path,
            structured_trace=self.logger.trace_path,
        )
        self._set_busy(False)
        self._refresh_secondary_actions_menu()
        if failed or not_applicable:
            self._notify_user(
                f"Update run finished with attention needed: {summary_body}. "
                f"See the operation log and diagnostic trace: {self.logger.trace_path}",
                level="warning",
                summary=summary,
            )
        elif cancelled:
            self._notify_user(
                f"Update run finished: {summary_body}. {cancelled} update(s) were cancelled.",
                level="warning",
                summary=summary,
            )
        elif skipped:
            self._notify_user(
                f"Update run finished: {summary_body}. {skipped} item(s) were skipped.",
                level="info",
                summary=summary,
            )
        else:
            message = f"Finished: {summary_body}."
            if with_warnings:
                message += f" {with_warnings} completed with warnings; review the log."
            if reboot_required:
                message += f" Restart Windows to finish {reboot_required} update(s)."
            self._notify_user(
                message,
                level="warning" if with_warnings or reboot_required else "success",
                summary=summary,
            )
        if results:
            self._verification_update_id = self.active_update_id
            self._post_update_refresh_outcomes.clear()
            update_items = attempt_items
            self._verification_results = {
                key: {
                    "item": item_diagnostic_fields(update_items[key]),
                    "result": dict(entry),
                }
                for entry in results
                if (key := str(entry.get("key", ""))) in update_items
            }
            self._append_log(
                "Refreshing attempted package providers first; untouched provider snapshots "
                "under three minutes old may be retained…"
            )
            self.logger.event(
                "post_update_verification_scheduled",
                update_id=self.active_update_id,
                successful_count=succeeded,
                result_count=len(results),
                verification_mode="staged-provider-scan-with-recent-snapshot-reuse",
                recent_snapshot_grace_seconds=POST_UPDATE_PROVIDER_REUSE_GRACE_SECONDS,
            )
            self._cancel_after_id("_post_update_scan_after_id")
            self._schedule_post_update_scan()
            if not self._scan_active:
                self._active_operation_items.clear()
                self._active_operation_results.clear()
        else:
            self._active_operation_items.clear()
            self._active_operation_results.clear()
            self.active_update_id = ""

    def _schedule_post_update_scan(self) -> None:
        self._cancel_after_id("_post_update_scan_after_id")
        self._refresh_scan_view_buttons()
        self._post_update_scan_after_id = self.root.after_idle(
            self._run_post_update_scan
        )

    def _run_post_update_scan(self) -> None:
        self._post_update_scan_after_id = None
        if self._closing:
            return
        if self.busy or self._scan_active:
            self._post_update_scan_after_id = self.root.after(
                250, self._run_post_update_scan
            )
            return
        self._start_scan(origin="post-update-verification")

    def cancel(self) -> None:
        if self._scan_active and (not self.busy or self._busy_kind == "scan"):
            if self._scan_cancel_requested.is_set():
                return
            self._scan_cancel_requested.set()
            self._activity_base = "Stopping scan"
            self.summary_var.set("Stopping the scan; providers already running will finish…")
            self.cancel_button.configure(state="disabled")
            self._append_log(
                "Scan stop requested; providers already running will finish, and queued "
                "providers will be skipped"
            )
            self.logger.event(
                "scan_stop_requested",
                scan_generation=self._active_scan_generation,
            )
            return
        if not self.busy or self.cancel_requested.is_set():
            return
        self.cancel_requested.set()
        if self._busy_kind == "selected-preflight":
            self._activity_base = "Stopping the selected-update checks"
            self.summary_var.set("Stopping the checks — no installer has started")
            self.cancel_button.configure(state="disabled")
            self._append_log("Stop requested during selected-update checks; no installer will start")
            return
        if self._busy_kind == "portable-scan":
            self._activity_base = "Stopping portable scan"
            self.summary_var.set("Stopping the portable scan…")
            self.cancel_button.configure(state="disabled")
            self._append_log("Portable scan stop requested")
            self.logger.event("portable_scan_stop_requested")
            return
        elevated_batch_inflight = self._busy_kind == "update" and bool(
            self._elevated_batch_inflight
        )
        if elevated_batch_inflight:
            self.summary_var.set(
                "Stop requested; the current administrator phase may finish…"
            )
            administrator_phase = (
                "already running in this administrator process"
                if self.process_is_admin
                else "already handed to the elevated helper"
            )
            self._append_log(
                "Stop requested; no later user-phase work will start, but the machine batch "
                f"{administrator_phase} may continue"
            )
        else:
            self.summary_var.set("Stop requested; the current package will finish first…")
            self._append_log("Stop requested; no new package operations will start")
        self.logger.event(
            "update_stop_requested",
            update_id=self.active_update_id,
            elevated_batch_already_dispatched=elevated_batch_inflight,
        )

    def _poll_events(self) -> None:
        # A nested Tk event loop must not take the outer poll's batch or timer.
        if getattr(self, "_event_poll_active", False):
            return
        self._poll_after_id = None
        if self._closing:
            return
        self._event_poll_active = True
        if getattr(self, "_ui_log_batch", None) is None:
            self._ui_log_batch = []
        batch_native_interaction = False
        backlog = False
        try:
            batch_native_interaction = self._native_window_interaction_active()
            started = time.perf_counter()
            for _index in range(UI_EVENT_BATCH_LIMIT):
                try:
                    kind, payload = self.events.get_nowait()
                except queue.Empty:
                    break
                try:
                    self._dispatch_event(kind, payload)
                except Exception as exc:
                    self.logger.event(
                        "ui_event_handler_error",
                        kind=kind,
                        error=f"{type(exc).__name__}: {exc}",
                    )
                    self._notify_user(
                        f"Internal UI event handling error for {kind}: "
                        f"{type(exc).__name__}: {exc}",
                        level="error",
                        summary="Internal UI event error; polling continued",
                    )
                if time.perf_counter() - started >= UI_EVENT_TIME_BUDGET_SECONDS:
                    backlog = True
                    break
            else:
                backlog = True
            writer_error = self.logger.consume_writer_error()
            if writer_error:
                self._notify_user(
                    f"Session logging encountered an error: {writer_error}",
                    level="warning",
                    summary="Session logging is incomplete",
                )
        finally:
            try:
                messages, self._ui_log_batch = self._ui_log_batch or [], None
                if messages and not self._closing:
                    paint_started = time.perf_counter()
                    self._paint_log_messages(messages)
                    self.logger.event(
                        "perf_probe",
                        probe="ui_log_batch_tk",
                        duration_ms=round(
                            (time.perf_counter() - paint_started) * 1000.0, 3
                        ),
                        message_count=len(messages),
                        line_count=sum(
                            max(1, len(message.splitlines())) for message in messages
                        ),
                        native_interaction=batch_native_interaction,
                        logger_queue=self.logger.queue_depth_metrics(),
                    )
            finally:
                self._event_poll_active = False
                if not self._closing:
                    delay = (
                        UI_EVENT_BACKLOG_DELAY_MS
                        if backlog
                        else UI_EVENT_BUSY_DELAY_MS
                        if self.busy or self._scan_active
                        else UI_EVENT_BACKGROUND_DELAY_MS
                        if self._background_event_work_active()
                        else UI_EVENT_IDLE_DELAY_MS
                    )
                    self._poll_after_id = self.root.after(delay, self._poll_events)

    def _background_event_work_active(self) -> bool:
        """Keep background-result latency low without busy-polling an idle UI."""

        return bool(
            getattr(self, "_winget_enrichment_active", False)
            or getattr(self, "_date_sleuth_active", False)
            or getattr(self, "_portable_scan_active", False)
            or getattr(self, "_portable_cache_verification_active", False)
            or getattr(self, "_portable_local_refresh_active", False)
            or getattr(self, "_portable_catalog_refresh_active", False)
            or getattr(self, "_lazy_icon_batch_active", False)
            or getattr(self, "_icon_prepare_inflight", ())
            or getattr(self, "_icon_background_sweep_active", False)
            or getattr(self, "_details_background_active", False)
            or getattr(self, "_details_background_inflight", False)
            or getattr(self, "_icon_catalog_write_active", False)
            or getattr(self, "_installed_inventory_cache_write_active", False)
            or getattr(self, "_icon_gallery_active_jobs", 0)
            or getattr(self, "_cache_clear_inflight", False)
            or getattr(self, "_diagnostic_bundle_inflight", False)
        )

    def _dispatch_event(self, kind: str, payload: Any) -> None:
        if kind == "ui_callback":
            callback, arguments = payload
            if not self._closing:
                callback(*arguments)
        elif kind == "log":
            self._append_log(str(payload))
        elif kind == "scan_log":
            generation, message = payload
            if generation == self._active_scan_generation:
                self._append_log(str(message))
        elif kind == "scan_notice":
            generation, provider_key, phase, message = payload
            if generation == self._active_scan_generation:
                notice_key = (str(provider_key), str(phase), str(message))
                first_in_session = notice_key not in self._provider_notice_seen
                self._provider_notice_seen.add(notice_key)
                self._append_log(str(message), show_in_ui=first_in_session)
        elif kind == "scan_plan":
            self._apply_scan_plan(*payload)
        elif kind == "scan_progress":
            handler_started = time.perf_counter()
            native_interaction = self._native_window_interaction_active()
            self._show_scan_progress(*payload)
            self.logger.event(
                "perf_probe",
                probe="scan_progress_tk",
                duration_ms=round((time.perf_counter() - handler_started) * 1000.0, 3),
                native_interaction=native_interaction,
                logger_queue=self.logger.queue_depth_metrics(),
            )
        elif kind == "post_update_provider_updates":
            self._apply_post_update_provider_updates(*payload)
        elif kind == "scan_inventory_provider":
            handler_started = time.perf_counter()
            native_interaction = self._native_window_interaction_active()
            self._apply_scan_inventory_provider(*payload)
            self.logger.event(
                "perf_probe",
                probe="scan_inventory_provider_tk",
                duration_ms=round((time.perf_counter() - handler_started) * 1000.0, 3),
                provider=str(payload[1]),
                package_count=len(payload[3]),
                native_interaction=native_interaction,
                logger_queue=self.logger.queue_depth_metrics(),
            )
        elif kind == "scan_done":
            finish_started = time.perf_counter()
            native_interaction = self._native_window_interaction_active()
            self._last_finish_scan_stage_ms = {}
            self._finish_scan(*payload)
            self.logger.event(
                "perf_probe",
                probe="finish_scan_tk",
                duration_ms=round((time.perf_counter() - finish_started) * 1000.0, 3),
                native_interaction=native_interaction,
                stages_ms=dict(self._last_finish_scan_stage_ms),
                logger_queue=self.logger.queue_depth_metrics(),
            )
        elif kind == "installed_inventory_cached":
            self._finish_installed_inventory_cache_write(*payload)
        elif kind == "portable_scan_done":
            self._finish_portable_scan(*payload)
        elif kind == "portable_scan_progress":
            self._show_portable_scan_progress(payload)
        elif kind == "portable_cache_verified":
            self._finish_portable_cache_verification(*payload)
        elif kind == "portable_local_versions_done":
            self._finish_portable_local_refresh(*payload)
        elif kind == "portable_catalog_done":
            self._finish_portable_catalog_refresh(*payload)
        elif kind == "winget_enriched":
            self._apply_winget_enrichment(*payload)
        elif kind == "winget_enrichment_done":
            self._finish_winget_enrichment(payload)
        elif kind == "icon_resolution_done":
            self._finish_icon_priority_resolution(*payload)
        elif kind == "icon_prepared":
            self._finish_icon_prepare(*payload)
        elif kind == "warm_icon_cache_indexed":
            self._finish_warm_icon_cache_restore(*payload)
        elif kind == "icon_catalog_loaded":
            self._finish_icon_catalog_load(*payload)
        elif kind == "icon_catalog_written":
            self._finish_icon_catalog_write(*payload)
        elif kind == "details_icon_prepared":
            self._finish_details_icon_prepare(*payload)
        elif kind == "details_icon_cache_indexed":
            self._finish_background_details_icon_index(*payload)
        elif kind == "details_icon_prefetched":
            self._finish_background_details_icon_prepare(*payload)
        elif kind == "vector_icon_resident":
            self._finish_vector_icon_resident(*payload)
        elif kind == "idle_dates_done":
            self._finish_idle_date_sleuth(*payload)
        elif kind == "item_status":
            key, status, index, total = payload
            item = self._set_scan_view_item_status(key, status)
            if item is not None:
                self._activity_base = (
                    f"[{index}/{total}] {status.rstrip('…')} {item.name}"
                )
            if self._busy_kind != "update":
                self._set_progress_value((index - 1) * 100 / max(1, total))
        elif kind == "command_result":
            handler_started = time.perf_counter()
            self._show_command_result(*payload)
            if self._busy_kind == "update" and payload[0].key in self._active_operation_items:
                self._update_progress_completed_keys.add(payload[0].key)
                self._set_progress_value(
                    len(self._update_progress_completed_keys) * 100
                    / max(1, len(self._active_operation_items))
                )
            self.logger.event(
                "perf_probe",
                probe="command_result_tk",
                duration_ms=round((time.perf_counter() - handler_started) * 1000.0, 3),
                logger_queue=self.logger.queue_depth_metrics(),
            )
        elif kind == "update_done":
            handler_started = time.perf_counter()
            self._finish_update(*payload)
            self.logger.event(
                "perf_probe",
                probe="finish_update_tk",
                duration_ms=round((time.perf_counter() - handler_started) * 1000.0, 3),
                logger_queue=self.logger.queue_depth_metrics(),
            )
        elif kind == "uninstall_done":
            self._finish_uninstall(*payload)
        elif kind == "suggested_install_done":
            self._finish_suggested_install(*payload)
        elif kind == "caches_cleared":
            self._finish_cache_clear(*payload)
        elif kind == "diagnostic_bundle_done":
            self._finish_diagnostic_bundle(str(payload))
        elif kind == "selected_preflight_done":
            self._finish_selected_winget_preflight(*payload)
        elif kind == "worker_failed":
            self._finish_worker_failure(payload)
        elif kind == "operation_heartbeat":
            update_id, item_key, name, elapsed_seconds = payload
            if (
                update_id == self.active_update_id
                and self._scan_view_item(item_key) is not None
            ):
                self._activity_base = f"Updating {name} ({elapsed_seconds}s elapsed)"
                self._append_log(
                    f"{name} is still working ({elapsed_seconds}s elapsed)"
                    + (
                        "; the installer may be downloading, configuring, or waiting for "
                        "the application to close"
                        if elapsed_seconds >= 90
                        else ""
                    )
                )

    @staticmethod
    def _close_requires_confirmation(busy: bool, busy_kind: str) -> bool:
        return busy and busy_kind in {"update", "uninstall", "install"}

    def _on_close(self) -> None:
        if self._closing:
            return
        # Read-only scans, verification, enrichment, and icon preparation are
        # safe to abandon immediately. Only an active package mutation needs
        # the warning that closing the UI cannot retract an installer already
        # handed to Windows.
        if self._close_requires_confirmation(self.busy, self._busy_kind):
            elevated_note = ""
            if self._elevated_batch_inflight:
                administrator_actor = (
                    "This administrator process may leave an already-started machine installer "
                    "running"
                    if self.process_is_admin
                    else "The already-authorized administrator helper may continue its current batch"
                )
                elevated_note = (
                    f"\n\n{administrator_actor}. Run Scan after reopening; that fresh "
                    "inventory is authoritative."
                )
            if not self.messagebox.askyesno(
                APP_NAME,
                "A package operation is still running. Closing the window will not safely "
                f"cancel an installer.{elevated_note}\n\nClose anyway?",
            ):
                return
        self._closing = True
        self._stop_package_list_motion()
        self._stop_package_gallery_motion()
        if hold := getattr(self, "_resize_hold", None):
            hold.close()
        if self.busy:
            self.cancel_requested.set()
        if self._scan_active:
            self._scan_cancel_requested.set()
        for attr_name in (
            "_activity_after_id",
            "_notification_after_id",
            "_progress_after_id",
            "_update_request_cue_after_id",
            "_nav_indicator_after_id",
            "_rebuild_after_id",
            "_package_gallery_after_id",
            "_package_gallery_icons_after_id",
            "_details_idle_after_id",
            "_log_paint_after_id",
            "_header_gradient_after_id",
            "_accent_gradient_after_id",
            "_main_splitter_sync_after_id",
            "_poll_after_id",
            "_theme_poll_after_id",
            "_icon_renderer_warm_after_id",
            "_initial_scan_after_id",
            "_visual_diagnostics_after_id",
            "_post_update_scan_after_id",
            "_tooltip_after_id",
            "_icon_hydration_after_id",
            "_icon_key_release_after_id",
            "_icon_memory_load_after_id",
            "_icon_memory_priority_after_id",
            "_icon_catalog_decode_after_id",
            "_icon_catalog_write_after_id",
            "_icon_sort_refresh_after_id",
            "_icon_gallery_photo_decode_after_id",
            "_icon_background_sweep_after_id",
            "_icon_background_progress_after_id",
            "_details_background_after_id",
            "_details_background_progress_after_id",
            "_icon_batch_finish_after_id",
            "_date_sleuth_after_id",
        ):
            self._cancel_after_id(attr_name)
        self.settings.data["window_geometry"] = self.root.geometry()
        self.settings.data["window_geometry_dpi"] = self.visuals.current_dpi
        self._capture_view_preferences()
        with contextlib.suppress(OSError):
            self.settings.save()
        completed_operation_keys = {
            key
            for entry in self._active_operation_results
            if (key := str(entry.get("key", "")))
        }
        unresolved_elevated_items = [
            item_diagnostic_fields(item)
            for key, item in self._active_operation_items.items()
            if item.requires_admin and key not in completed_operation_keys
        ]
        if self._elevated_batch_inflight and unresolved_elevated_items:
            self.logger.write(
                "Window closed while the administrator phase still had "
                f"{len(unresolved_elevated_items)} unresolved package(s); run Scan after "
                "reopening to reconcile their installed versions."
            )
            self.logger.event(
                "elevation_batch_detached",
                update_id=self.active_update_id,
                execution_context=(
                    "already-elevated-process"
                    if self.process_is_admin
                    else "elevated-helper"
                ),
                completed_result_count=len(completed_operation_keys),
                unresolved_item_count=len(unresolved_elevated_items),
                items=unresolved_elevated_items,
            )
        self.logger.event(
            "session_end",
            busy=self.busy,
            busy_kind=self._busy_kind,
            stop_requested=self.cancel_requested.is_set(),
            scan_active=self._scan_active,
            scan_stop_requested=self._scan_cancel_requested.is_set(),
            active_update_id=self.active_update_id,
            elevated_batch_inflight=self._elevated_batch_inflight,
            active_operation_item_count=len(self._active_operation_items),
            completed_result_count=len(completed_operation_keys),
            unresolved_elevated_items=unresolved_elevated_items,
        )
        self._icon_gallery_preparations.clear()
        self._icon_gallery_bundle_bytes = 0
        self._icon_gallery_bundle_report_threshold = ICON_GALLERY_MEMORY_REPORT_START
        self._icon_gallery_blit_cache.clear()
        self._icon_gallery_blit_bytes = 0
        self._icon_gallery_blit_report_threshold = ICON_GALLERY_BLIT_MEMORY_REPORT_START
        self._icon_gallery_blit_warmup_announced = False
        self._icon_gallery_photo_decode_queue.clear()
        self._icon_gallery_photo_decode_pending.clear()
        self._icon_gallery_queued_jobs.clear()
        self._icon_gallery_job_heap.clear()
        try:
            self.root.destroy()
        finally:
            self.icon_renderer.shutdown(timeout=0.5)
            if threading.excepthook == self._installed_threading_excepthook:
                threading.excepthook = self._previous_threading_excepthook
            self.logger.close(timeout=0.5)

    def run(self) -> int:
        self.root.mainloop()
        return 0


def scan_json() -> int:
    path_report = refresh_process_path_from_windows_environment()
    settings = SettingsStore()
    providers = build_providers()
    provider_availability = {
        key: provider.available() for key, provider in providers.items()
    }
    unavailable_provider_keys = material_unavailable_provider_keys(
        providers,
        settings.data["providers"],
        provider_availability,
    )
    portable_inventory = PortableInventoryStore()
    found_updates: list[UpdateItem] = []
    found_packages: list[UpdateItem] = []
    output: dict[str, Any] = {
        "schema": 1,
        "app": APP_NAME,
        "version": APP_VERSION,
        "checked_at": utc_now_iso(),
        "updates": [],
        "installed_packages": [],
        "portable_cache": {},
        "attempt_holds": {},
        "warnings": [],
        "errors": [],
        "unavailable_providers": sorted(unavailable_provider_keys),
        "path_recovery": dataclasses.asdict(path_report),
    }
    for key, provider in providers.items():
        if not settings.data["providers"].get(key, provider.default_enabled):
            continue
        if not provider_availability[key]:
            continue

        def collect_warnings(phase: str) -> None:
            output["warnings"].extend(
                {"provider": key, "phase": phase, "warning": warning}
                for warning in provider.warnings
            )
            provider.warnings.clear()
            incomplete_reasons = list(dict.fromkeys(provider.phase_incomplete_reasons))
            if incomplete_reasons:
                output["errors"].append(
                    {
                        "provider": key,
                        "phase": phase,
                        "error": "incomplete provider result: "
                        + "; ".join(incomplete_reasons),
                    }
                )
            provider.phase_incomplete_reasons.clear()

        try:
            provider.warnings.clear()
            provider.phase_incomplete_reasons.clear()
            updates = provider.discover()
            if isinstance(provider, WingetProvider):
                updates = provider._preflight_items(updates)
            found_updates.extend(stable_identity_instances(updates))
        except Exception as exc:
            output["errors"].append(
                {
                    "provider": key,
                    "phase": "updates",
                    "error": f"{type(exc).__name__}: {exc}",
                }
            )
        finally:
            collect_warnings("updates")
        try:
            provider.warnings.clear()
            provider.phase_incomplete_reasons.clear()
            found_packages.extend(stable_identity_instances(provider.discover_all()))
        except Exception as exc:
            output["errors"].append(
                {
                    "provider": key,
                    "phase": "installed-packages",
                    "error": f"{type(exc).__name__}: {exc}",
                }
            )
        finally:
            collect_warnings("installed-packages")

    portable_records = portable_inventory.records()
    portable_advisories = [
        advisory
        for record in portable_records
        if (advisory := portable_record_to_update_item(record)) is not None
    ]
    found_updates.extend(portable_advisories)
    found_packages.extend(portable_record_to_item(record) for record in portable_records)
    found_updates = stable_identity_instances(
        deduplicate_microsoft_store_inventory(found_updates)
    )
    found_packages = stable_identity_instances(
        deduplicate_microsoft_store_inventory(found_packages)
    )
    package_dates = getattr(providers.get(MICROSOFT_STORE_PROVIDER_KEY), "native_package_dates", {})
    apply_windows_package_dates(found_updates, package_dates)
    apply_windows_package_dates(found_packages, package_dates)
    apply_known_product_variant_names(found_updates)
    apply_known_product_variant_names(found_packages)
    visible_updates = apply_stored_selection_policy(found_updates, settings.data)
    visible_packages = apply_stored_selection_policy(found_packages, settings.data)

    def serialize_item(item: UpdateItem) -> dict[str, Any]:
        return {
            **dataclasses.asdict(item),
            "candidate_key": item.candidate_key,
            "installed_size_display": human_size_from_kb(item.installed_size_kb),
        }

    output["updates"] = [serialize_item(item) for item in visible_updates]
    output["installed_packages"] = [serialize_item(item) for item in visible_packages]
    output["portable_cache"] = {
        "record_count": len(portable_records),
        "advisory_count": len(portable_advisories),
        "warning": portable_inventory.warning,
    }
    if portable_inventory.warning:
        output["warnings"].append(
            {
                "provider": "portable-cache",
                "phase": "installed-packages",
                "warning": portable_inventory.warning,
            }
        )
    output["attempt_holds"] = attempt_hold_scan_summary(
        settings.data, {item.candidate_key for item in visible_updates}
    )
    output["complete"] = not output["errors"] and not unavailable_provider_keys
    print(json.dumps(output, indent=2))
    return 0 if output["complete"] else 1


def display_diagnostics() -> int:
    """Report the exact native/Tk rendering path without starting a scan."""
    if os.name != "nt":
        print(json.dumps({"platform": sys.platform, "supported": False}, indent=2))
        return 2
    dpi_bootstrap = configure_windows_dpi_awareness()
    import tkinter as tk

    root = tk.Tk()
    root.withdraw()
    visuals = WindowsVisualController(root, dpi_bootstrap)
    try:
        visuals.initialize()
        root.update_idletasks()
        root.update()
        diagnostics = visuals.diagnostics()
        diagnostics["theme_mode"] = app_palette()["mode"]
        print(json.dumps(diagnostics, indent=2, sort_keys=True))
        return 0
    finally:
        root.destroy()


def microsoft_store_self_test() -> None:
    """Exercise Store parsing and mutation boundaries without contacting Windows."""

    assert SettingsStore._defaults()["providers"][MicrosoftStoreProvider.key] is True
    store_item = UpdateItem(
        provider=MicrosoftStoreProvider.key,
        name="Example Store App",
        package_id="9NBLGGH4NNS1",
        current="1.0.0.0",
        available="1.1.0.0",
        source=MICROSOFT_STORE_SOURCE,
        scope="user",
        requires_admin=False,
    )
    store_command = MicrosoftStoreProvider().build_update_command(store_item)
    assert store_command[:5] == [
        "winget",
        "upgrade",
        "--id",
        "9NBLGGH4NNS1",
        "--exact",
    ]
    assert store_command[store_command.index("--source") + 1] == MICROSOFT_STORE_SOURCE
    assert "--scope" not in store_command and "--version" in store_command
    store_uninstall = MicrosoftStoreProvider().build_uninstall_command(store_item)
    assert store_uninstall[:5] == [
        "winget",
        "uninstall",
        "--id",
        "9NBLGGH4NNS1",
        "--exact",
    ]
    store_table = """Name              Id           Version  Available
--------------------------------------------------------
Example Store App  9NBLGGH4NNS1 1.0.0.0  1.1.0.0
"""
    assert MicrosoftStoreProvider._table_rows(store_table, updates=True) == [
        {
            "Name": "Example Store App",
            "Id": "9NBLGGH4NNS1",
            "Version": "1.0.0.0",
            "Available": "1.1.0.0",
        }
    ]
    store_internal_error = CommandResult(
        returncode=WINGET_INTERNAL_ERROR,
        output="",
        command=["winget", "list", "--source", "msstore"],
    )
    assert MicrosoftStoreProvider._catalog_failure_message(store_internal_error) == (
        "WinGet reported an internal error (0x8A150001) while reading the "
        "Microsoft Store catalog"
    )
    store_other_error = CommandResult(
        returncode=5,
        output="catalog fixture failure",
        command=["winget", "list", "--source", "msstore"],
    )
    assert "0x00000005 (5): catalog fixture failure" in (
        MicrosoftStoreProvider._catalog_failure_message(store_other_error)
    )
    saved_store_run_capture = globals()["run_capture"]
    saved_store_which = shutil.which
    try:
        shutil.which = lambda executable: (
            r"C:\Fixture\winget.exe" if executable == "winget" else saved_store_which(executable)
        )
        globals()["run_capture"] = lambda command, **_kwargs: CommandResult(
            0,
            "No installed package found matching input criteria.\r\n",
            list(command),
        )
        native_empty_store = MicrosoftStoreProvider()
        assert not native_empty_store._catalog_rows(updates=True)
        assert not native_empty_store.phase_incomplete_reasons

        globals()["run_capture"] = lambda command, **_kwargs: CommandResult(
            0,
            "Unrecognized Store catalog response",
            list(command),
        )
        untrusted_empty_store = MicrosoftStoreProvider()
        assert not untrusted_empty_store._catalog_rows(updates=True)
        assert untrusted_empty_store.phase_incomplete_reasons

        globals()["run_capture"] = lambda command, **_kwargs: CommandResult(
            WINGET_NO_APPLICATIONS_FOUND,
            "",
            list(command),
        )
        coded_empty_store = MicrosoftStoreProvider()
        assert not coded_empty_store._catalog_rows(updates=True)
        assert not coded_empty_store.phase_incomplete_reasons

        shutil.which = lambda executable: (
            None if executable == "winget" else saved_store_which(executable)
        )
        missing_winget_store = MicrosoftStoreProvider()
        assert not missing_winget_store._catalog_rows(updates=True)
        assert missing_winget_store.phase_incomplete_reasons
    finally:
        globals()["run_capture"] = saved_store_run_capture
        shutil.which = saved_store_which
    desktop_inventory = WindowsInstalledInventory(
        [
            RegistryInstallEntry(
                display_name="UniGetUI",
                display_version="3.2.0",
                scope="machine",
                technology="exe",
                install_location=r"C:\Program Files\UniGetUI",
            )
        ]
    )
    desktop_catalog_item = MicrosoftStoreProvider._apply_catalog_applicability_guard(
        MicrosoftStoreProvider._enrich_catalog_item(
            UpdateItem(
                provider=MicrosoftStoreProvider.key,
                name="UniGetUI",
                package_id="XPFFTQ032PTPHF",
                current="3.2.0",
                available="2026.2.7",
                source=MICROSOFT_STORE_SOURCE,
                scope="user",
                requires_admin=False,
                selected=True,
                status="Ready",
                classification=CLASS_SIMPLE_UPGRADE,
            ),
            desktop_inventory,
        )
    )
    assert desktop_catalog_item.installed_for == "machine"
    assert desktop_catalog_item.installed_technology == "exe"
    assert not desktop_catalog_item.selected
    assert desktop_catalog_item.classification == CLASS_SCOPE_OR_APPLICABILITY
    assert desktop_catalog_item.applicability_prediction == PREDICTION_NOT_APPLICABLE
    assert desktop_catalog_item.prediction_source == "store-scope-technology-guard"
    store_provider = MicrosoftStoreProvider()
    assert (
        store_provider._actionable_catalog_update(dataclasses.replace(desktop_catalog_item))
        is None
    )
    assert store_provider.suppressed_updates == [
        {
            "reason": "store-desktop-channel-conflict",
            "name": "UniGetUI",
            "package_id": "XPFFTQ032PTPHF",
            "installed_version": "3.2.0",
            "store_catalog_version": "2026.2.7",
            "installed_for": "machine",
            "installed_technology": "exe",
            "installed_location": r"C:\Program Files\UniGetUI",
            "status": "Store offer does not match this desktop installation",
        }
    ]
    try:
        MicrosoftStoreProvider().build_update_command(desktop_catalog_item)
    except ValueError as exc:
        assert "machine-wide desktop installation" in str(exc)
    else:
        raise AssertionError("Store command was built for a machine-wide desktop app")
    native_store_item = inventory_only_item(
        provider=MicrosoftStoreProvider.key,
        name="Example Store App",
        package_id="MSIX\\Example.App_1.0.0.0_x64__publisher",
        current="1.0.0.0",
        source="store-inventory",
    )
    duplicate_winget_item = inventory_only_item(
        provider=WingetProvider.key,
        name="Example Store App",
        package_id="MSIX\\Example.App_1.0.0.0_x64__publisher",
        current="1.0.0.0",
        source="winget",
    )
    assert deduplicate_microsoft_store_inventory(
        [duplicate_winget_item, native_store_item]
    ) == [native_store_item]


# ==================== Deterministic safety and behavior fixtures ====================

def cache_lifecycle_self_test() -> None:
    """Exercise persistence and cache lifetimes without scans, Tk, or installers."""

    from unittest.mock import Mock, patch

    base = inventory_only_item(
        provider="winget", name="Cache fixture", package_id="Fixture.Cache",
        current="1.0", source="winget", scope="user",
    )
    base.installed_location = r"C:\Fixture\App"
    observed_at = dt.datetime(2026, 9, 5, 12, 0, tzinfo=dt.UTC)
    evidence = dataclasses.replace(
        base, installed_date="2026-09-04", installed_timestamp="2026-09-04T01:02:03.123456+00:00",
        installed_timestamp_precision="fractional-6", installed_date_is_estimate=True,
        installed_date_source="Corroborated local install-folder creation times (approximate)",
    )
    for changes in ({"current": "2.0"}, {"scope": "machine"}, {"source": "msstore"},
                    {"installed_location": r"C:\Elsewhere"},
                    {"installed_registration_changed_at": "2026-09-05T12:00:00+00:00"},
                    {"product_codes": ("new-registration",)},
                    {"installed_date": "2026-09-05"}):
        assert reuse_cached_service_dates([dataclasses.replace(base, **changes)], [evidence]) == 0
    with tempfile.TemporaryDirectory(prefix="wdp-cache-lifecycle-") as temp:
        root = Path(temp)
        store = InstalledInventoryStore(root / "inventory.json")
        snapshot = InstalledInventorySnapshot(
            (dataclasses.replace(base),), frozenset({"winget"}), observed_at,
            {}, {"winget": observed_at.isoformat()}, {},
        )
        app = object.__new__(WinDevPilotApp)
        app._closing = False
        app._date_sleuth_generation = 1
        app._date_sleuth_active = True
        app._date_sleuth_can_start = lambda: True
        app._date_sleuth_signature = lambda: "fixture"
        live = dataclasses.replace(base)
        app.items = {live.key: live}
        app._scan_view_items = {False: {}, True: app.items}
        app._sort_state = None
        app._refresh_item_row = Mock()
        app._details_refinement_listeners = []
        app._append_log = Mock()
        app.logger = Mock()
        app._observation_inventory_snapshot = snapshot
        app._active_scan_generation = 10
        app._installed_inventory_cache_write_generation = 0
        app.installed_inventory = store
        app.events = queue.Queue()
        result = (installed_item_date_identity(live), evidence.installed_date,
                  evidence.installed_timestamp, evidence.installed_timestamp_precision, True,
                  evidence.installed_date_source, ())
        with patch.object(threading, "Thread") as thread:
            app._finish_idle_date_sleuth(1, "fixture", 1, [result], False, "")
            assert thread.call_count == 1
            thread.call_args.kwargs["target"]()
        loaded = InstalledInventoryStore(store.path)
        assert not loaded.warning
        assert not snapshot.items[0].installed_timestamp  # Published snapshots stay immutable.
        assert loaded.snapshot.scanned_at == observed_at
        assert loaded.snapshot.provider_scanned_at == snapshot.provider_scanned_at
        assert loaded.snapshot.items[0].installed_timestamp == evidence.installed_timestamp
        rescanned = dataclasses.replace(base)
        assert reuse_cached_service_dates([rescanned], loaded.snapshot.items) == 1
        assert rescanned.installed_date_is_estimate
        assert reuse_cached_service_dates([rescanned], loaded.snapshot.items) == 0

        source = root / "fixture.exe"
        source.write_bytes(b"fixture; never executed")
        source_stat = source.stat()
        entry = {
            "identity": list(item_icon_identity(base)), "version": base.current,
            "source": str(source), "source_stat": [source_stat.st_mtime_ns, source_stat.st_size],
        }
        entries = {base.key: entry, "shared-source": dict(entry)}
        real_stat = Path.stat
        with patch.object(Path, "stat", autospec=True, side_effect=real_stat) as source_probe:
            assert not changed_icon_catalog_keys(entries, [base])
            assert source_probe.call_count == 1
        assert changed_icon_catalog_keys(entries, [dataclasses.replace(base, current="2.0")]) == {base.key}
        source.write_bytes(b"replacement fixture; never executed")
        assert changed_icon_catalog_keys(entries, [base]) == set(entries)
        source.unlink()
        assert changed_icon_catalog_keys(entries, [base]) == set(entries)
        source.write_bytes(b"fixture; never executed")
        current_stat = source.stat()
        entry["source_stat"] = [current_stat.st_mtime_ns, current_stat.st_size]
        catalog = root / "catalog.json"
        raw = root / "raw.png"
        with patch(f"{__name__}.icon_cache_dir", return_value=root), patch(
            f"{__name__}.icon_catalog_path", return_value=catalog,
        ):
            write_icon_render_miss(raw, 72, "fixture")
            deadline = icon_render_miss_expires_at(raw, 72)
            entry.update(list_unavailable=True, list_unavailable_until=deadline)
            assert icon_catalog_miss_is_current(entry, "list")
            catalog.write_text(json.dumps({**icon_catalog_compatibility(), "entries": {base.key: entry}}))
            assert load_icon_catalog_and_blobs()[0][base.key]["list_unavailable"]
            with patch(f"{__name__}.time.time", return_value=deadline + 1):
                assert not icon_render_miss_is_current(raw, 72)
                assert not icon_catalog_miss_is_current(entry, "list")
                assert not load_icon_catalog_and_blobs()[0][base.key].get("list_unavailable")
                assert changed_icon_catalog_keys({base.key: entry}, [base]) == {base.key}
            legacy = {key: value for key, value in entry.items() if key != "list_unavailable_until"}
            assert not icon_catalog_miss_is_current(legacy, "list")

    app = object.__new__(WinDevPilotApp)
    app._closing = False
    app.tk = type("TkFixture", (), {"TclError": RuntimeError})
    old_key, keep_key = ("old", 32, "dark"), ("keep", 32, "dark")
    app._icon_catalog_write_generation = 0
    app._icon_catalog_write_active = True
    app._warm_icon_restore_generation = 0
    app._icon_catalog_entries = {"old": {}, "keep": {}}
    app._item_icon_source_cache = {"old": None, "keep": None}
    app._icon_gallery_preparations = {"old": {}, "keep": {}}
    app._icon_gallery_bundle_bytes = 0
    app._icon_gallery_queued_jobs = {"old": (), "keep": ()}
    superseded = Mock()
    app._icon_gallery_inflight = {"old": [superseded]}
    app._icon_prepare_inflight = {old_key, keep_key}
    app._details_icon_callbacks = {}
    app._package_icon_images = {old_key: object(), keep_key: object()}
    app._details_icon_images = DecodedIconCache(app._package_icon_images.items())
    app._package_icon_ready = {old_key, keep_key}
    app._package_icon_misses = {old_key, keep_key}
    app._icon_catalog_decode_queue = deque([("old", 32, "old.png"), ("keep", 32, "keep.png")])
    app._icon_catalog_valid_paths = set()
    app.logger = Mock()
    app._invalidate_item_icon_caches({"old"})
    assert set(app._package_icon_images) == set(app._details_icon_images) == {keep_key}
    assert app._package_icon_ready == app._package_icon_misses == {keep_key}
    assert set(app._icon_catalog_entries) == set(app._icon_gallery_preparations) == {"keep"}
    assert set(app._icon_gallery_queued_jobs) == {"keep"}
    assert list(app._icon_catalog_decode_queue) == [("keep", 32, "keep.png")]
    assert not app._icon_gallery_inflight and not app._icon_catalog_write_active
    superseded.assert_called_once()
    assert app._icon_catalog_write_generation == app._warm_icon_restore_generation == 1
    app._icon_showcase_cache = OrderedDict()
    app._icon_showcase_inflight = {}
    closed_callback = Mock()  # A closed popup's presenter is a no-op.
    reopened_callback = Mock()
    callbacks = [closed_callback, reopened_callback]
    app._icon_showcase_inflight["shared"] = callbacks
    app._finish_icon_showcase_request("shared", callbacks, b"png", "nearest", {}, "")
    assert app._icon_showcase_cache["shared"] == (b"png", "nearest", {})
    assert not app._icon_showcase_inflight
    reopened_callback.assert_called_once_with(b"png", "nearest", {}, "")
    failed = [Mock()]
    app._icon_showcase_inflight["failed"] = failed
    app._finish_icon_showcase_request("failed", failed, b"", "", {}, "fixture failure")
    assert "failed" not in app._icon_showcase_cache and "failed" not in app._icon_showcase_inflight
    failed[0].assert_called_once()
    newer = [Mock()]
    app._icon_showcase_inflight["shared"] = newer
    app._finish_icon_showcase_request("shared", callbacks, b"stale", "", {}, "")
    assert app._icon_showcase_inflight["shared"] is newer
    assert app._icon_showcase_cache["shared"][0] == b"png"
    newer[0].assert_not_called()
    for index in range(20):
        pending: list[Callable[..., None]] = []
        key = str(index)
        app._icon_showcase_inflight[key] = pending
        app._finish_icon_showcase_request(key, pending, b"png", "nearest", {}, "")
    assert len(app._icon_showcase_cache) == 16


def self_test() -> int:
    """Run independent suites even if another suite reports a failure."""
    if not __debug__:
        print("self-test requires assertions; rerun without python -O", file=sys.stderr)
        return 2
    return _run_self_test_sections((
        ("microsoft-store", microsoft_store_self_test),
        ("icon-cache", cache_lifecycle_self_test),
        ("vector-artwork", vector_icon_self_test),
        ("application", _application_self_test),
    ))


def _run_self_test_sections(sections: Iterable[tuple[str, Callable[[], None]]]) -> int:
    failed = 0
    for name, check in sections:
        try:
            check()
        except Exception:
            failed += 1
            print(f"FAIL self-test: {name}", file=sys.stderr)
            traceback.print_exc()
        else:
            print(f"PASS self-test: {name}")
    print(f"{APP_NAME} self-test {'failed' if failed else 'passed'}")
    return 1 if failed else 0


def _application_self_test() -> None:
    from types import SimpleNamespace
    from unittest.mock import Mock, patch

    # Synthetic color bands independently exercise the multicolor boundary.
    def color_fixture(*bands: tuple[tuple[int, int, int, int], int]) -> bytes:
        pixels = b"".join(bytes(rgba) * count for rgba, count in bands)
        assert len(pixels) == 400
        return rgba_png_bytes(10, 10, [pixels[offset:offset+40] for offset in range(0, 400, 40)])

    red, cyan, magenta = (255, 0, 0, 255), (0, 255, 255, 255), (255, 0, 255, 255)
    for bands, rainbow in (
        (((red, 44), (cyan, 45), (magenta, 11)), True),
        (((red, 45), (cyan, 45), (magenta, 10)), False),
        (((red, 34), (cyan, 55), (magenta, 11)), False),
        (((red, 31), (cyan, 57), (magenta, 12)), True),
        (((red, 50), (cyan, 50)), False),
        (((cyan, 100),), False),
        ((((255, 0, 0, 255), 34), ((255, 255, 0, 255), 33), ((0, 255, 0, 255), 33)), False),
    ):
        key = icon_rainbow_sort_key(color_fixture(*bands))
        assert (key[:2] == (0, 1.0)) == rainbow, (bands, key)
    assert icon_rainbow_sort_key(color_fixture(((128, 128, 128, 255), 100)))[0] == 1
    assert icon_rainbow_sort_key(color_fixture(((0, 0, 0, 0), 100)))[0] == 2
    elevation_type = windows_token_elevation_type()
    assert elevation_type in {"unknown", "default", "full", "limited"}
    identity_diagnostics = process_identity_diagnostics()
    assert identity_diagnostics["elevation_type"] in {
        "unknown",
        "default",
        "full",
        "limited",
    }
    assert redact_log_value(identity_diagnostics)["elevation_type"] == identity_diagnostics[
        "elevation_type"
    ]
    self_command = cached_self_command("--version")
    assert self_command[:2] == [sys.executable, "-X"]
    assert self_command[2].startswith("pycache_prefix=")
    assert Path(self_command[2].partition("=")[2]).parent == app_data_dir()
    assert self_command[3:] == ["-m", SCRIPT_PATH.stem, "--version"]
    assert not WinDevPilotApp._close_requires_confirmation(False, "")
    assert not WinDevPilotApp._close_requires_confirmation(True, "scan")
    assert not WinDevPilotApp._close_requires_confirmation(True, "pip-verify")
    assert WinDevPilotApp._close_requires_confirmation(True, "update")
    assert WinDevPilotApp._close_requires_confirmation(True, "uninstall")
    assert WinDevPilotApp._close_requires_confirmation(True, "install")
    original_hbitmap_rows = globals()["_hbitmap_rgba_rows"]
    try:
        globals()["_hbitmap_rgba_rows"] = lambda _hbitmap: None
        assert _hbitmap_png_bytes(1) is None
    finally:
        globals()["_hbitmap_rgba_rows"] = original_hbitmap_rows
    with tempfile.TemporaryDirectory(prefix="WinDevPilot-icon-prune-") as temp_dir:
        prune_root = Path(temp_dir)
        fresh_temporary = prune_root / ".fresh.tmp"
        aged_temporary = prune_root / ".aged.raw.png"
        obsolete_icon = prune_root / "appicon-v0-obsolete.png"
        for path in (fresh_temporary, aged_temporary, obsolete_icon):
            path.write_bytes(b"fixture")
        old_timestamp = time.time() - 2 * 60 * 60
        os.utime(aged_temporary, (old_timestamp, old_timestamp))
        original_icon_cache_dir = globals()["icon_cache_dir"]
        try:
            globals()["icon_cache_dir"] = lambda: prune_root
            assert prune_stale_icon_cache_versions() == 2
        finally:
            globals()["icon_cache_dir"] = original_icon_cache_dir
        assert fresh_temporary.exists()
        assert not aged_temporary.exists()
        assert not obsolete_icon.exists()
    with tempfile.TemporaryDirectory(prefix="WinDevPilot-data-migration-") as temp_dir:
        migration_root = Path(temp_dir)
        legacy_data = migration_root / LEGACY_APP_DATA_NAME
        legacy_data.mkdir()
        (legacy_data / "settings.json").write_text("{}", encoding="utf-8")
        assert migrate_legacy_app_data(migration_root)
        assert not legacy_data.exists()
        assert (migration_root / APP_NAME / "settings.json").read_text(
            encoding="utf-8"
        ) == "{}"
        assert not migrate_legacy_app_data(migration_root)

    variant_items = [
        inventory_only_item(
            provider="winget",
            name="Claude",
            package_id="Anthropic.Claude",
            current="1",
            source="winget",
        ),
        inventory_only_item(
            provider="winget",
            name="Claude Code",
            package_id="Anthropic.ClaudeCode",
            current="2",
            source="winget",
        ),
        inventory_only_item(
            provider=MICROSOFT_STORE_PROVIDER_KEY,
            name="ChatGPT",
            package_id="MSIX\\OpenAI.Codex_26.825.6671.0_x64__publisher",
            current="26.825.6671.0",
            source="store-inventory",
        ),
        inventory_only_item(
            provider="npm",
            name="@openai/codex",
            package_id="@openai/codex",
            current="0.152.0",
            source="npm global",
        ),
    ]
    apply_known_product_variant_names(variant_items)
    assert [item.name for item in variant_items] == [
        "Claude (Desktop app)",
        "Claude Code (CLI)",
        "Codex (Desktop app)",
        "Codex (CLI)",
    ]
    assert known_product_variant_name("winget", "Example.App", "Example") == "Example"

    cached_inventory_item = inventory_only_item(
        provider=WingetProvider.key,
        name="Cached inventory fixture",
        package_id="Example.CachedInventory",
        current="3.2.0",
        source="winget",
    )
    cached_inventory_item.installed_date = "2026-08-29"
    cached_inventory_item.installed_timestamp = "2026-08-29T08:34:56.789123-04:00"
    cached_inventory_item.installed_timestamp_precision = "fractional-6"
    cached_inventory_item.installed_registration_changed_at = (
        "2026-08-29T12:35:01.234567+00:00"
    )
    cached_inventory_item.installed_registration_changed_at_precision = "fractional-6"
    replacement_inventory_item = inventory_only_item(
        provider=PipProvider.key,
        name="Replacement inventory fixture",
        package_id="replacement-fixture",
        current="2.0.0",
        source="pip",
    )
    replaced_inventory = replace_inventory_provider_rows(
        {cached_inventory_item.key: cached_inventory_item},
        [replacement_inventory_item],
        {PipProvider.key},
    )
    assert set(replaced_inventory) == {
        cached_inventory_item.key,
        replacement_inventory_item.key,
    }
    emptied_inventory = replace_inventory_provider_rows(
        replaced_inventory,
        [],
        {WingetProvider.key},
    )
    assert set(emptied_inventory) == {replacement_inventory_item.key}
    with tempfile.TemporaryDirectory(prefix="WinDevPilot-inventory-cache-") as temp_dir:
        cache_path = Path(temp_dir) / INSTALLED_INVENTORY_CACHE_FILENAME
        scanned_at = dt.datetime(2026, 8, 29, 12, 34, 56, 789123, tzinfo=dt.UTC)
        cache_store = InstalledInventoryStore(cache_path)
        cache_store.replace(
            [cached_inventory_item],
            {WingetProvider.key, PipProvider.key},
            scanned_at,
            {},
            {
                WingetProvider.key: datetime_storage_timestamp(scanned_at),
                PipProvider.key: datetime_storage_timestamp(scanned_at),
            },
            provider_started_at={key: datetime_storage_timestamp(scanned_at)
                                 for key in (WingetProvider.key, PipProvider.key)},
        )
        reloaded_cache = InstalledInventoryStore(cache_path)
        assert not reloaded_cache.warning
        assert reloaded_cache.snapshot.scanned_at == scanned_at
        assert reloaded_cache.snapshot.provider_keys == frozenset(
            {WingetProvider.key, PipProvider.key}
        )
        assert set(reloaded_cache.snapshot.provider_scanned_at) == {
            WingetProvider.key,
            PipProvider.key,
        }
        cached_rows = reloaded_cache.items_for({WingetProvider.key})
        assert len(cached_rows) == 1
        assert cached_rows[0] == cached_inventory_item
        assert cached_rows[0] is not cached_inventory_item
        assert cached_rows[0].installed_timestamp.endswith("-04:00")
        assert reloaded_cache.items_for({PipProvider.key}) == ()
        legacy_path = Path(temp_dir) / "legacy-installed-inventory.json"
        legacy_payload = json.loads(cache_path.read_text(encoding="utf-8"))
        legacy_payload["schema"] = 3
        legacy_payload.pop("provider_started_at", None)
        for field in (
            "installed_timestamp",
            "installed_timestamp_precision",
            "installed_registration_changed_at",
            "installed_registration_changed_at_precision",
        ):
            legacy_payload["items"][0].pop(field)
        legacy_path.write_text(json.dumps(legacy_payload), encoding="utf-8")
        migrated_cache = InstalledInventoryStore(legacy_path)
        assert not migrated_cache.warning
        migrated_item = migrated_cache.items_for({WingetProvider.key})[0]
        assert not migrated_item.installed_timestamp
        assert migrated_item.installed_timestamp_precision == "date"
        newly_offered = dataclasses.replace(
            cached_inventory_item,
            classification=CLASS_SIMPLE_UPGRADE,
            selected=True,
            available="3.3.0",
        )
        observations = evolve_update_observations(
            reloaded_cache.snapshot,
            [newly_offered],
            {WingetProvider.key, PipProvider.key},
            scanned_at + dt.timedelta(hours=2),
            {
                WingetProvider.key: (
                    scanned_at + dt.timedelta(hours=2)
                ).isoformat(timespec="microseconds"),
                PipProvider.key: (
                    scanned_at + dt.timedelta(hours=2)
                ).isoformat(timespec="microseconds"),
            },
        )
        observation = observations[update_observation_identity_key(newly_offered)]
        assert observation["last_absent_at"] == datetime_storage_timestamp(scanned_at)
        assert observation["first_seen_at"] == (
            scanned_at + dt.timedelta(hours=2)
        ).isoformat(timespec="microseconds")
        repeated_observations = evolve_update_observations(
            InstalledInventorySnapshot(
                items=reloaded_cache.snapshot.items,
                provider_keys=reloaded_cache.snapshot.provider_keys,
                scanned_at=scanned_at + dt.timedelta(hours=2),
                update_observations=observations,
                provider_scanned_at={
                    WingetProvider.key: (
                        scanned_at + dt.timedelta(hours=2)
                    ).isoformat(timespec="microseconds"),
                    PipProvider.key: (
                        scanned_at + dt.timedelta(hours=2)
                    ).isoformat(timespec="microseconds"),
                },
                provider_started_at={
                    WingetProvider.key: (
                        scanned_at + dt.timedelta(hours=2)
                    ).isoformat(timespec="microseconds"),
                    PipProvider.key: (
                        scanned_at + dt.timedelta(hours=2)
                    ).isoformat(timespec="microseconds"),
                },
            ),
            [dataclasses.replace(newly_offered, available="3.3")],
            {WingetProvider.key, PipProvider.key},
            scanned_at + dt.timedelta(hours=3),
            {
                WingetProvider.key: (
                    scanned_at + dt.timedelta(hours=3)
                ).isoformat(timespec="microseconds"),
                PipProvider.key: (
                    scanned_at + dt.timedelta(hours=3)
                ).isoformat(timespec="microseconds"),
            },
        )
        repeated = repeated_observations[update_observation_identity_key(newly_offered)]
        assert repeated["last_absent_at"] == observation["last_absent_at"]
        assert repeated["first_seen_at"] == observation["first_seen_at"]
        assert repeated["last_seen_at"] != observation["last_seen_at"]
        relabeled_offer = dataclasses.replace(
            newly_offered,
            source="provider display label changed",
            instance=7,
        )
        assert update_observation_identity_key(relabeled_offer) == (
            update_observation_identity_key(newly_offered)
        )
        relabeled_observations = evolve_update_observations(
            reloaded_cache.snapshot,
            [relabeled_offer],
            {WingetProvider.key},
            scanned_at + dt.timedelta(hours=4),
            {
                WingetProvider.key: (
                    scanned_at + dt.timedelta(hours=4)
                ).isoformat(timespec="microseconds")
            },
        )
        assert relabeled_observations[
            update_observation_identity_key(relabeled_offer)
        ]["last_absent_at"] == ""  # A changed registration starts a new baseline.

        lifecycle_start = dt.datetime(2026, 9, 3, 8, 0, 0, 100001, tzinfo=dt.UTC)
        lifecycle_first = dt.datetime(2026, 9, 3, 10, 0, 0, 200002, tzinfo=dt.UTC)
        lifecycle_changed = dt.datetime(2026, 9, 3, 12, 0, 0, 300003, tzinfo=dt.UTC)
        lifecycle_item = dataclasses.replace(cached_inventory_item, current="1.2.3")
        lifecycle_baseline = InstalledInventorySnapshot(
            items=(lifecycle_item,),
            provider_keys=frozenset({WingetProvider.key}),
            scanned_at=lifecycle_start,
            provider_scanned_at={WingetProvider.key: lifecycle_start.isoformat()},
            provider_started_at={WingetProvider.key: lifecycle_start.isoformat()},
        )
        lifecycle_records = evolve_installation_observations(
            lifecycle_baseline,
            [lifecycle_item],
            {WingetProvider.key},
            {WingetProvider.key},
            {WingetProvider.key: lifecycle_first.isoformat()},
        )
        lifecycle_key = update_observation_identity_key(lifecycle_item)
        assert lifecycle_records[lifecycle_key]["transition_kind"] == "baseline"
        assert lifecycle_records[lifecycle_key]["first_seen_at"] == lifecycle_start.isoformat()
        assert not installation_observation_date_evidence(
            lifecycle_item, lifecycle_records
        ).date
        lifecycle_snapshot = InstalledInventorySnapshot(
            items=(lifecycle_item,),
            provider_keys=frozenset({WingetProvider.key}),
            scanned_at=lifecycle_first,
            provider_scanned_at={WingetProvider.key: lifecycle_first.isoformat()},
            provider_started_at={WingetProvider.key: lifecycle_first.isoformat()},
            installation_observations=lifecycle_records,
        )
        changed_item = dataclasses.replace(lifecycle_item, current="2.0.0")
        changed_records = evolve_installation_observations(
            lifecycle_snapshot,
            [changed_item],
            {WingetProvider.key},
            {WingetProvider.key},
            {WingetProvider.key: lifecycle_changed.isoformat()},
        )
        changed_record = changed_records[lifecycle_key]
        assert changed_record["transition_kind"] == "version-changed"
        assert changed_record["previous_version"] == "1.2.3"
        assert changed_record["lower_bound_at"] == lifecycle_first.isoformat()
        changed_evidence = installation_observation_date_evidence(
            changed_item, changed_records
        )
        assert changed_evidence.date == "2026-09-03"
        assert changed_evidence.display_text == "≈ 2026-09-03"
        assert changed_evidence.observation_kind == "version-changed"
        assert "complete inventories" in changed_evidence.source
        changed_snapshot = InstalledInventorySnapshot(
            items=(changed_item,),
            provider_keys=frozenset({WingetProvider.key}),
            scanned_at=lifecycle_changed,
            provider_scanned_at={WingetProvider.key: lifecycle_changed.isoformat()},
            provider_started_at={WingetProvider.key: lifecycle_changed.isoformat()},
            installation_observations=changed_records,
        )
        repeated_at = lifecycle_changed + dt.timedelta(hours=1)
        repeated_lifecycle = evolve_installation_observations(
            changed_snapshot,
            [dataclasses.replace(changed_item, current="2.0")],
            {WingetProvider.key},
            {WingetProvider.key},
            {WingetProvider.key: repeated_at.isoformat()},
        )
        assert repeated_lifecycle[lifecycle_key]["first_seen_at"] == (
            lifecycle_changed.isoformat()
        )
        assert repeated_lifecycle[lifecycle_key]["last_seen_at"] == repeated_at.isoformat()
        assert evolve_installation_observations(
            changed_snapshot,
            [changed_item],
            {WingetProvider.key},
            set(),
            {WingetProvider.key: lifecycle_changed.isoformat()},
        ) == changed_records  # A reused provider cannot advance observation time.
        assert evolve_installation_observations(
            changed_snapshot,
            [dataclasses.replace(changed_item, current="Unknown")],
            {WingetProvider.key},
            {WingetProvider.key},
            {WingetProvider.key: repeated_at.isoformat()},
        ) == changed_records  # A placeholder cannot manufacture a transition.
        absent_at = lifecycle_changed + dt.timedelta(hours=2)
        absent_records = evolve_installation_observations(
            changed_snapshot,
            [],
            {WingetProvider.key},
            {WingetProvider.key},
            {WingetProvider.key: absent_at.isoformat()},
        )
        assert absent_records[lifecycle_key]["state"] == "absent"
        assert absent_records[lifecycle_key]["last_absent_at"] == absent_at.isoformat()
        absent_snapshot = InstalledInventorySnapshot(
            items=(),
            provider_keys=frozenset({WingetProvider.key}),
            scanned_at=absent_at,
            provider_scanned_at={WingetProvider.key: absent_at.isoformat()},
            provider_started_at={WingetProvider.key: absent_at.isoformat()},
            installation_observations=absent_records,
        )
        returned_at = lifecycle_changed + dt.timedelta(hours=3)
        returned_records = evolve_installation_observations(
            absent_snapshot,
            [changed_item],
            {WingetProvider.key},
            {WingetProvider.key},
            {WingetProvider.key: returned_at.isoformat()},
        )
        assert returned_records[lifecycle_key]["transition_kind"] == (
            "installed-or-reappeared"
        )
        assert returned_records[lifecycle_key]["lower_bound_at"] == absent_at.isoformat()
        first_install_item = dataclasses.replace(
            lifecycle_item, package_id="Example.FirstInstalled", current="1.0.0"
        )
        first_install_records = evolve_installation_observations(
            lifecycle_baseline,
            [lifecycle_item, first_install_item],
            {WingetProvider.key},
            {WingetProvider.key},
            {WingetProvider.key: lifecycle_first.isoformat()},
        )
        first_install_record = first_install_records[
            update_observation_identity_key(first_install_item)
        ]
        assert first_install_record["transition_kind"] == "installed-or-reappeared"
        assert first_install_record["lower_bound_at"] == lifecycle_start.isoformat()
        duplicate = dataclasses.replace(changed_item, source="second-source", instance=1)
        ambiguous_records = evolve_installation_observations(
            changed_snapshot,
            [changed_item, duplicate],
            {WingetProvider.key},
            {WingetProvider.key},
            {WingetProvider.key: returned_at.isoformat()},
        )
        assert ambiguous_records[lifecycle_key]["state"] == "ambiguous"
        assert not installation_observation_date_evidence(changed_item, ambiguous_records).date
        assert not evolve_installation_observations(
            InstalledInventorySnapshot(
                provider_keys=frozenset({WingetProvider.key}),
                scanned_at=absent_at,
                provider_scanned_at={WingetProvider.key: absent_at.isoformat()},
                provider_started_at={WingetProvider.key: absent_at.isoformat()},
            ),
            [dataclasses.replace(changed_item, current="Unknown")],
            {WingetProvider.key},
            {WingetProvider.key},
            {WingetProvider.key: returned_at.isoformat()},
        )
        cross_midnight = dict(
            returned_records[lifecycle_key],
            lower_bound_at="2026-09-03T23:55:00-04:00",
            first_seen_at="2026-09-04T00:05:00-04:00",
        )
        assert installation_observation_date_evidence(
            changed_item, {lifecycle_key: cross_midnight}
        ).display_text == "≈ 2026-09-03–2026-09-04"
        relabeled_item = dataclasses.replace(changed_item, source="new display source", instance=9)
        assert installation_observation_date_evidence(
            relabeled_item, returned_records
        ).date == "2026-09-03"
        assert not installation_observation_date_evidence(
            dataclasses.replace(changed_item, current="3.0"), returned_records
        ).date
        assert installed_service_date_evidence(
            changed_item, {}, changed_records
        ) == changed_evidence
        native_same_day = dataclasses.replace(
            changed_item,
            installed_date="2026-09-03",
            installed_date_source="provider date",
        )
        assert installed_service_date_evidence(
            native_same_day, {}, changed_records
        ).source == "provider date"
        lifecycle_cache_path = Path(temp_dir) / "lifecycle-cache.json"
        lifecycle_store = InstalledInventoryStore(lifecycle_cache_path)
        lifecycle_store.replace(
            [changed_item],
            {WingetProvider.key},
            lifecycle_changed,
            {},
            {WingetProvider.key: lifecycle_changed.isoformat()},
            changed_records,
        )
        lifecycle_reload = InstalledInventoryStore(lifecycle_cache_path)
        assert lifecycle_reload.snapshot.installation_observations == changed_records

        # The cache worker owns the published observation snapshot, even if a
        # newer scan changes the GUI rows and replaces all observation maps.
        handoff_path = Path(temp_dir) / "handoff-cache.json"
        handoff_app = object.__new__(WinDevPilotApp)
        handoff_app.installed_inventory = InstalledInventoryStore(handoff_path)
        handoff_app._installed_inventory_cache_write_generation = 0
        handoff_app.events = queue.Queue()
        handoff_app.logger = Mock()
        handoff_app._append_log = Mock()
        handoff_row = dataclasses.replace(changed_item)
        handoff_old = dataclasses.replace(
            lifecycle_reload.snapshot,
            items=(dataclasses.replace(handoff_row),),
        )
        handoff_new_time = lifecycle_changed + dt.timedelta(seconds=1, microseconds=12)
        handoff_new_row = dataclasses.replace(handoff_row, current="4.0.0")
        handoff_new_times = {WingetProvider.key: datetime_storage_timestamp(handoff_new_time)}
        handoff_new = InstalledInventorySnapshot(
            (handoff_new_row,),
            handoff_old.provider_keys,
            handoff_new_time,
            {},
            handoff_new_times,
            evolve_installation_observations(
                handoff_old, (handoff_new_row,), handoff_old.provider_keys,
                handoff_old.provider_keys, handoff_new_times,
            ),
        )
        with patch.object(threading, "Thread") as handoff_thread:
            handoff_app._observation_inventory_snapshot = handoff_old
            handoff_app._write_installed_inventory_cache_async(handoff_old, 10)
            handoff_row.current = "GUI changed after publication"
            handoff_app._observation_inventory_snapshot = handoff_new
            handoff_app._write_installed_inventory_cache_async(handoff_new, 11)
            handoff_jobs = [call.kwargs["target"] for call in handoff_thread.call_args_list]
        handoff_jobs[0]()
        assert InstalledInventoryStore(handoff_path).snapshot.items[0].current == changed_item.current
        handoff_app._finish_installed_inventory_cache_write(*handoff_app.events.get_nowait()[1])
        assert handoff_app._installed_inventory_cache_write_active
        handoff_jobs[1]()
        handoff_app._finish_installed_inventory_cache_write(*handoff_app.events.get_nowait()[1])
        assert not handoff_app._installed_inventory_cache_write_active
        handoff_saved = handoff_path.read_bytes()
        handoff_jobs[0]()
        assert handoff_path.read_bytes() == handoff_saved
        handoff_app.events.get_nowait()
        handoff_reload = InstalledInventoryStore(handoff_path)
        assert not handoff_reload.warning
        assert handoff_reload.snapshot.scanned_at == handoff_new_time
        assert handoff_reload.snapshot.installation_observations == handoff_new.installation_observations
        assert json.loads(handoff_saved)["items"] == json.loads(json.dumps([
            dataclasses.asdict(dataclasses.replace(handoff_new_row, selected=False))
        ]))
        with patch.object(handoff_app.installed_inventory, "replace", side_effect=OSError("fixture")):
            handoff_jobs[1]()
        failed_handoff = handoff_app.events.get_nowait()[1]
        assert failed_handoff == (2, 11, 1, "OSError: fixture")
        assert handoff_path.read_bytes() == handoff_saved

        generation_cache_path = Path(temp_dir) / "generation-cache.json"
        generation_cache = InstalledInventoryStore(generation_cache_path)
        assert generation_cache.replace(
            [cached_inventory_item],
            {WingetProvider.key},
            scanned_at,
            {},
            {WingetProvider.key: datetime_storage_timestamp(scanned_at)},
            write_generation=2,
        )
        assert not generation_cache.replace(
            [dataclasses.replace(cached_inventory_item, current="stale")],
            {WingetProvider.key},
            scanned_at - dt.timedelta(hours=1),
            {},
            {
                WingetProvider.key: (
                    scanned_at - dt.timedelta(hours=1)
                ).isoformat(timespec="microseconds")
            },
            write_generation=1,
        )
        assert generation_cache.snapshot.items[0].current == "3.2.0"
        assert json.loads(generation_cache_path.read_text(encoding="utf-8"))[
            "scanned_at"
        ] == datetime_storage_timestamp(scanned_at)
        current_payload = json.loads(cache_path.read_text(encoding="utf-8"))
        legacy_payload = dict(current_payload)
        legacy_payload["schema"] = 1
        legacy_payload.pop("provider_started_at", None)
        legacy_payload.pop("update_observations")
        legacy_payload.pop("provider_scanned_at")
        legacy_payload.pop("installation_observations")
        cache_path.write_text(json.dumps(legacy_payload), encoding="utf-8")
        legacy_cache = InstalledInventoryStore(cache_path)
        assert not legacy_cache.warning
        assert legacy_cache.snapshot.items
        assert not legacy_cache.snapshot.update_observations
        assert set(legacy_cache.snapshot.provider_scanned_at) == {
            WingetProvider.key,
            PipProvider.key,
        }
        schema_2_payload = dict(current_payload)
        schema_2_payload["schema"] = 2
        schema_2_payload.pop("provider_started_at", None)
        schema_2_payload.pop("installation_observations")
        cache_path.write_text(json.dumps(schema_2_payload), encoding="utf-8")
        schema_2_cache = InstalledInventoryStore(cache_path)
        assert not schema_2_cache.warning
        assert schema_2_cache.snapshot.items
        assert not schema_2_cache.snapshot.installation_observations
        malformed_payload = current_payload
        malformed_payload["items"][0]["selected"] = True
        cache_path.write_text(json.dumps(malformed_payload), encoding="utf-8")
        rejected_cache = InstalledInventoryStore(cache_path)
        assert not rejected_cache.snapshot.items
        assert "actionable row" in rejected_cache.warning

    row_probe = object.__new__(WinDevPilotApp)
    row_probe.settings = type("RowSettingsFixture", (), {"data": {}})()
    row_probe._provisional_inventory_keys = {cached_inventory_item.key}
    row_probe.providers = {WingetProvider.key: WingetProvider()}
    row_probe.process_is_admin = False
    cached_row_values = WinDevPilotApp._item_row_values(
        row_probe, cached_inventory_item
    )
    assert cached_row_values[3] == "Checking…"
    assert cached_row_values[4] == "Checking…"
    assert len(cached_row_values) == 8
    assert cached_row_values[7] == "Previous inventory"
    assert WinDevPilotApp._uninstall_route(row_probe, cached_inventory_item) is None

    class RebuildRootFixture:
        def __init__(self) -> None:
            self.next_id = 0
            self.callbacks: dict[str, Callable[[], None]] = {}

        def after(self, _delay: int, callback: Callable[[], None]) -> str:
            self.next_id += 1
            callback_id = f"after-{self.next_id}"
            self.callbacks[callback_id] = callback
            return callback_id

        def after_cancel(self, callback_id: str) -> None:
            self.callbacks.pop(callback_id, None)

    rebuild_probe = object.__new__(WinDevPilotApp)
    rebuild_probe.root = RebuildRootFixture()
    rebuild_probe._rebuild_after_id = None
    rebuild_probe._rebuild_prime_cached_first_paint = False
    rebuild_probe.logger = Mock()
    rebuild_probe.items = {}
    rebuild_probe._last_scan_all_packages = False
    rebuild_probe._scan_active = False
    rebuild_calls: list[bool] = []
    rebuild_probe._rebuild_tree = lambda *, prime_cached_first_paint=False: (
        rebuild_calls.append(prime_cached_first_paint)
    )
    WinDevPilotApp._schedule_rebuild_tree(rebuild_probe)
    WinDevPilotApp._schedule_rebuild_tree(
        rebuild_probe,
        prime_cached_first_paint=True,
    )
    WinDevPilotApp._schedule_rebuild_tree(rebuild_probe)
    assert len(rebuild_probe.root.callbacks) == 1
    next(iter(rebuild_probe.root.callbacks.values()))()
    assert rebuild_calls == [True]

    checkpoint_probe = object.__new__(WinDevPilotApp)
    checkpoint_probe._closing = False
    checkpoint_probe._warm_icon_restore_generation = 1
    checkpoint_probe._active_scan_generation = 1
    checkpoint_probe._icon_prepare_generation = 1
    checkpoint_probe.items = {cached_inventory_item.key: cached_inventory_item}
    checkpoint_probe._item_icon_source_cache = {}
    checkpoint_probe._package_icon_ready = set()
    checkpoint_probe._package_icon_misses = set()
    checkpoint_probe._package_icon_images = {}
    checkpoint_probe.palette = {"mode": "light"}
    checkpoint_probe.visuals = type("CheckpointVisuals", (), {"px": lambda _self, _dip: 24})()
    checkpoint_probe._icon_sort_active = False
    checkpoint_probe.logger = Mock()
    checkpoint_probe._schedule_icon_catalog_write = Mock()
    checkpoint_probe._schedule_ready_icon_memory_load = Mock()
    checkpoint_probe._schedule_visible_icon_hydration = Mock()
    checkpoint_probe._schedule_background_icon_sweep = Mock()
    warm_arguments = (
        1, 1, 1, WARM_ICON_CACHE_MIN_COUNT,
        {cached_inventory_item.key: Path("source.png")},
        [(cached_inventory_item.key, 24, "light")], [],
    )
    checkpoint_probe._finish_warm_icon_cache_restore(*warm_arguments, "")
    assert checkpoint_probe._schedule_icon_catalog_write.call_count == 1
    checkpoint_probe._schedule_icon_catalog_write.reset_mock()
    checkpoint_probe._finish_warm_icon_cache_restore(*warm_arguments, "index failed")
    assert not checkpoint_probe._schedule_icon_catalog_write.called
    checkpoint_probe._warm_icon_restore_generation = 2
    checkpoint_probe._finish_warm_icon_cache_restore(*warm_arguments, "")
    assert not checkpoint_probe._schedule_icon_catalog_write.called
    checkpoint_order: list[str] = []
    checkpoint_probe._schedule_icon_catalog_write = lambda: checkpoint_order.append("catalog")
    checkpoint_probe._start_background_details_icon_sweep = lambda: checkpoint_order.append("details")
    checkpoint_probe._icon_background_sweep_active = True
    checkpoint_probe._icon_background_sweep_queue = []
    checkpoint_probe._icon_prepare_inflight = set()
    checkpoint_probe._cancel_after_id = Mock()
    checkpoint_probe._background_icon_counts = lambda: (1, 0)
    checkpoint_probe._lazy_icon_batch_upscaled = 0
    checkpoint_probe._lazy_icon_batch_cached = 1
    checkpoint_probe._lazy_icon_batch_failed = 0
    checkpoint_probe._icon_background_sweep_total = 1
    checkpoint_probe._append_log = Mock()
    assert checkpoint_probe._finish_background_icon_sweep_if_idle()
    assert checkpoint_order == ["catalog", "details"]
    assert not checkpoint_probe._finish_background_icon_sweep_if_idle()
    assert checkpoint_order == ["catalog", "details"]

    old_winget_row = inventory_only_item(
        provider=WingetProvider.key,
        name="Joint publication fixture",
        package_id="Example.Joint.Old",
        current="1.0.0",
        source="winget",
    )
    old_store_row = inventory_only_item(
        provider=MicrosoftStoreProvider.key,
        name="Old Store fixture",
        package_id="9OLDSTORE",
        current="1.0.0",
        source=MICROSOFT_STORE_SOURCE,
    )
    fresh_winget_row = inventory_only_item(
        provider=WingetProvider.key,
        name="Joint publication fixture",
        package_id="9JOINTAPP",
        current="2.0.0",
        source=MICROSOFT_STORE_SOURCE,
    )
    fresh_store_row = inventory_only_item(
        provider=MicrosoftStoreProvider.key,
        name="Joint publication fixture",
        package_id="9JOINTAPP",
        current="2.0.0",
        source=MICROSOFT_STORE_SOURCE,
    )
    batch_probe = object.__new__(WinDevPilotApp)
    batch_probe._closing = False
    batch_probe._active_scan_generation = 91
    batch_probe._scan_active = True
    batch_probe.busy = False
    batch_probe._busy_kind = ""
    batch_probe._scan_expected_provider_keys = {
        WingetProvider.key,
        MicrosoftStoreProvider.key,
        "optional-missing-fixture",
    }
    batch_probe._scan_current_provider_keys = set()
    batch_probe._scan_provider_inventory_batches = {}
    batch_probe._scan_view_items = {
        False: {},
        True: {
            old_winget_row.key: old_winget_row,
            old_store_row.key: old_store_row,
        },
    }
    batch_probe._provisional_inventory_keys = {
        old_winget_row.key,
        old_store_row.key,
    }
    batch_probe._last_scan_all_packages = False
    batch_probe._icon_catalog_loaded = False
    batch_probe._observation_inventory_snapshot = InstalledInventorySnapshot()
    batch_probe.providers = {
        WingetProvider.key: WingetProvider(),
        MicrosoftStoreProvider.key: MicrosoftStoreProvider(),
    }
    batch_probe._refresh_scan_summary_counts = Mock()
    batch_probe.logger = type(
        "InventoryBatchFixtureLogger", (), {"event": lambda *_args, **_kwargs: None}
    )()
    WinDevPilotApp._apply_scan_plan(
        batch_probe,
        91,
        [WingetProvider.key, MicrosoftStoreProvider.key],
    )
    assert batch_probe._scan_expected_provider_keys == {
        WingetProvider.key,
        MicrosoftStoreProvider.key,
    }
    batch_probe._refresh_scan_summary_counts.assert_called_once_with()
    WinDevPilotApp._apply_scan_inventory_provider(
        batch_probe,
        91,
        WingetProvider.key,
        "WinGet",
        [fresh_winget_row],
        True,
    )
    assert set(batch_probe._scan_view_items[True]) == {
        old_winget_row.key,
        old_store_row.key,
    }
    WinDevPilotApp._apply_scan_inventory_provider(
        batch_probe,
        91,
        MicrosoftStoreProvider.key,
        "Microsoft Store",
        [fresh_store_row],
        True,
    )
    assert list(batch_probe._scan_view_items[True].values()) == [fresh_store_row]
    assert not batch_probe._provisional_inventory_keys
    assert batch_probe._refresh_scan_summary_counts.call_count == 1

    # Either provider can finish first. The existing joint publication barrier
    # joins exact dates before rows appear, and rejects late-generation evidence.
    joint_full_name = "Example.Joint_1.0.0.0_x64__publisher"
    joint_dates = windows_package_dates_from_records([{
        "full_name": joint_full_name, "installed_timestamp": "2026-08-20T15:16:17.123456Z",
    }])
    for provider_order in (("winget", "msstore"), ("msstore", "winget")):
        batch_probe._scan_current_provider_keys.clear()
        batch_probe._scan_provider_inventory_batches.clear()
        batch_probe._scan_windows_package_dates = {}
        batch_probe._scan_view_items = {False: {}, True: {}}
        joint_date_row = inventory_only_item(
            provider="winget", name="Native framework fixture",
            package_id="MSIX\\" + joint_full_name, current="1.0.0.0",
            source="winget", scope="user",
        )
        batch_probe._apply_scan_inventory_provider(
            90, "msstore", "Microsoft Store", (), True, windows_package_dates=joint_dates,
        )
        assert not batch_probe._scan_windows_package_dates
        batch_probe._apply_scan_inventory_provider(
            91, "msstore", "Microsoft Store", (), False, windows_package_dates=joint_dates,
        )
        assert not batch_probe._scan_windows_package_dates
        for index, provider_key in enumerate(provider_order):
            batch_probe._apply_scan_inventory_provider(
                91, provider_key, provider_key,
                [joint_date_row] if provider_key == "winget" else [], True,
                windows_package_dates=joint_dates if provider_key == "msstore" else {},
            )
            assert bool(batch_probe._scan_view_items[True]) == bool(index)
        published_date_row = next(iter(batch_probe._scan_view_items[True].values()))
        assert published_date_row.provider == "winget"
        assert published_date_row.installed_timestamp == joint_dates[joint_full_name.casefold()][0]

    class ScanFixtureProvider:
        executable = ""
        default_enabled = True
        recent_inventory_hits = 0

        def __init__(self, key: str, updates: list[UpdateItem], packages: list[UpdateItem]):
            self.key = key
            self.label = key
            self.warnings: list[str] = []
            self.suppressed_updates: list[dict[str, Any]] = []
            self.phase_incomplete_reasons: list[str] = []
            self.updates = updates
            self.packages = packages
            self.discover_calls = 0
            self.inventory_calls = 0

        def available(self) -> bool:
            return True

        def discover(self) -> list[UpdateItem]:
            self.discover_calls += 1
            return list(self.updates)

        def discover_all(self) -> list[UpdateItem]:
            self.inventory_calls += 1
            return list(self.packages)

    deferred_key = "deferred-fixture"
    live_key = "live-fixture"
    deferred_update = UpdateItem(
        deferred_key, "Deferred update", "Fixture.Deferred", "1", "2", "fixture"
    )
    deferred_package = dataclasses.replace(
        deferred_update, available="1", status="Installed - no update shown"
    )
    live_update = UpdateItem(live_key, "Live update", "Fixture.Live", "1", "2", "fixture")
    live_package = dataclasses.replace(
        live_update, available="1", status="Installed - no update shown"
    )
    deferred_provider = ScanFixtureProvider(deferred_key, [], [])
    live_provider = ScanFixtureProvider(live_key, [live_update], [live_package])
    scan_probe = object.__new__(WinDevPilotApp)
    scan_probe._scan_cancel_requested = threading.Event()
    scan_probe._provider_duration_hints = {}
    scan_probe._provider_operation_locks = {
        deferred_key: threading.RLock(),
        live_key: threading.RLock(),
    }
    scan_probe._active_operation_items = {deferred_update.key: deferred_update}
    scan_probe._active_operation_results = []
    scan_probe.events = queue.Queue()
    scan_probe.logger = type(
        "ScanFixtureLogger", (), {"event": lambda *_args, **_kwargs: None}
    )()
    original_build_providers = globals()["build_providers"]
    try:
        globals()["build_providers"] = lambda: {
            deferred_key: deferred_provider,
            live_key: live_provider,
        }
        WinDevPilotApp._scan_worker(
            scan_probe,
            77,
            {deferred_key: True, live_key: True},
            True,
            {
                deferred_key: ([deferred_update], [deferred_package]),
                live_key: ([], []),
            },
        )
    finally:
        globals()["build_providers"] = original_build_providers
    scan_done_payload = None
    scan_plan_payload = None
    while not scan_probe.events.empty():
        event_kind, event_payload = scan_probe.events.get_nowait()
        if event_kind == "scan_plan":
            scan_plan_payload = event_payload
        if event_kind == "scan_done":
            scan_done_payload = event_payload
    assert scan_plan_payload == (77, (deferred_key, live_key))
    assert scan_done_payload is not None
    assert {item.key for item in scan_done_payload[0]} == {
        deferred_update.key,
        live_update.key,
    }
    assert {item.key for item in scan_done_payload[1]} == {
        deferred_package.key,
        live_package.key,
    }
    assert scan_done_payload[10] == {deferred_key}
    assert scan_done_payload[11] is True
    assert scan_done_payload[12] == set()
    assert deferred_provider.discover_calls == deferred_provider.inventory_calls == 0
    assert live_provider.discover_calls == live_provider.inventory_calls == 1
    live_timing = next(timing for timing in scan_done_payload[5] if timing["key"] == live_key)
    assert valid_wall_clock_instant(live_timing["observation_started_at"], require_timezone=True)
    assert wall_clock_order_key(live_timing["observation_finished_at"]) >= wall_clock_order_key(live_timing["observation_started_at"])
    assert 0 < live_timing["observation_finished_monotonic"] <= time.monotonic()

    incomplete_key = "incomplete-fixture"
    incomplete_update = UpdateItem(
        incomplete_key,
        "Incomplete update",
        "Fixture.Incomplete",
        "1",
        "2",
        "fixture",
    )

    class IncompleteScanFixtureProvider(ScanFixtureProvider):
        def discover(self) -> list[UpdateItem]:
            self.phase_incomplete_reasons.append("one requested scope could not be read")
            return super().discover()

    incomplete_provider = IncompleteScanFixtureProvider(
        incomplete_key,
        [incomplete_update],
        [],
    )
    scan_probe.events = queue.Queue()
    scan_probe._provider_operation_locks = {incomplete_key: threading.RLock()}
    scan_probe._active_operation_items = {}
    try:
        globals()["build_providers"] = lambda: {incomplete_key: incomplete_provider}
        WinDevPilotApp._scan_worker(
            scan_probe,
            78,
            {incomplete_key: True},
            False,
            {},
        )
    finally:
        globals()["build_providers"] = original_build_providers
    incomplete_done = None
    while not scan_probe.events.empty():
        event_kind, event_payload = scan_probe.events.get_nowait()
        if event_kind == "scan_done":
            incomplete_done = event_payload
    assert incomplete_done is not None
    assert incomplete_key in incomplete_done[4]
    assert any(
        "incomplete provider result" in error for error in incomplete_done[2]
    )

    class IncompleteJsonFixtureProvider(Provider):
        key = "incomplete-json-fixture"
        label = "Incomplete JSON fixture"
        executable = ""
        default_enabled = True

        def available(self) -> bool:
            return True

        def discover(self) -> list[UpdateItem]:
            self.mark_phase_incomplete("fixture update scope was incomplete")
            return []

        def discover_all(self) -> list[UpdateItem]:
            return []

        def build_update_command(self, item: UpdateItem) -> list[str]:
            del item
            raise ValueError("fixture provider does not build update commands")

    original_refresh_path = globals()["refresh_process_path_from_windows_environment"]
    original_local_app_data = os.environ.get("LOCALAPPDATA")
    try:
        globals()["build_providers"] = lambda: {
            IncompleteJsonFixtureProvider.key: IncompleteJsonFixtureProvider()
        }
        globals()["refresh_process_path_from_windows_environment"] = (
            lambda: WindowsPathRefreshReport()
        )
        with tempfile.TemporaryDirectory(prefix="WinDevPilot-scan-json-") as temp_dir:
            os.environ["LOCALAPPDATA"] = temp_dir
            captured_json = io.StringIO()
            with contextlib.redirect_stdout(captured_json):
                incomplete_json_exit = scan_json()
            incomplete_json_payload = json.loads(captured_json.getvalue())
    finally:
        globals()["build_providers"] = original_build_providers
        globals()["refresh_process_path_from_windows_environment"] = original_refresh_path
        if original_local_app_data is None:
            os.environ.pop("LOCALAPPDATA", None)
        else:
            os.environ["LOCALAPPDATA"] = original_local_app_data
    assert incomplete_json_exit == 1
    assert incomplete_json_payload["complete"] is False
    assert any(
        entry["provider"] == IncompleteJsonFixtureProvider.key
        and entry["phase"] == "updates"
        and "fixture update scope was incomplete" in entry["error"]
        for entry in incomplete_json_payload["errors"]
    )

    priority_key = "priority-fixture"
    remainder_key = "remainder-fixture"
    attempted_update = UpdateItem(
        priority_key,
        "Attempted update",
        "Fixture.Attempted",
        "1",
        "2",
        "fixture",
    )
    attempted_package = dataclasses.replace(
        attempted_update,
        current="2",
        available="2",
        status="Installed - no update shown",
    )
    remainder_update = UpdateItem(
        remainder_key,
        "Remainder update",
        "Fixture.Remainder",
        "1",
        "2",
        "fixture",
    )
    remainder_package = dataclasses.replace(
        remainder_update, available="1", status="Installed - no update shown"
    )
    priority_provider = ScanFixtureProvider(
        priority_key, [], [attempted_package]
    )
    remainder_provider = ScanFixtureProvider(
        remainder_key, [remainder_update], [remainder_package]
    )
    priority_scan_probe = object.__new__(WinDevPilotApp)
    priority_scan_probe._scan_cancel_requested = threading.Event()
    priority_scan_probe._provider_duration_hints = {}
    priority_scan_probe._provider_operation_locks = {
        priority_key: threading.RLock(),
        remainder_key: threading.RLock(),
    }
    priority_scan_probe._active_operation_items = {}
    priority_scan_probe._active_operation_results = []
    priority_scan_probe._verification_update_id = "priority-update-fixture"
    priority_scan_probe.events = queue.Queue()
    priority_log_events: list[tuple[str, dict[str, Any]]] = []
    priority_scan_probe.logger = type(
        "PriorityScanFixtureLogger",
        (),
        {
            "event": lambda _self, name, **fields: priority_log_events.append(
                (name, fields)
            )
        },
    )()
    priority_events: list[tuple[str, Any]] = []
    original_build_providers = globals()["build_providers"]
    try:
        globals()["build_providers"] = lambda: {
            priority_key: priority_provider,
            remainder_key: remainder_provider,
        }
        WinDevPilotApp._scan_worker(
            priority_scan_probe,
            78,
            {priority_key: True, remainder_key: True},
            False,
            {
                priority_key: ([attempted_update], [attempted_package]),
                remainder_key: ([remainder_update], [remainder_package]),
            },
            {
                attempted_update.key: {
                    "item": item_diagnostic_fields(attempted_update),
                    "result": {"success": True, "outcome": "updated"},
                }
            },
            {remainder_key: time.monotonic()},
        )
    finally:
        globals()["build_providers"] = original_build_providers
    while not priority_scan_probe.events.empty():
        priority_events.append(priority_scan_probe.events.get_nowait())
    assert priority_provider.discover_calls == priority_provider.inventory_calls == 1
    assert remainder_provider.discover_calls == remainder_provider.inventory_calls == 0
    provider_update_event_index = next(
        index
        for index, event in enumerate(priority_events)
        if event[0] == "post_update_provider_updates"
    )
    priority_inventory_index = next(
        index
        for index, event in enumerate(priority_events)
        if event[0] == "scan_inventory_provider" and event[1][1] == priority_key
    )
    assert provider_update_event_index < priority_inventory_index
    scheduled_event = next(
        fields for name, fields in priority_log_events if name == "provider_scan_scheduled"
    )
    assert scheduled_event["scheduled_order"][0] == priority_key
    assert scheduled_event["attempted_provider_keys"] == [priority_key]
    assert set(scheduled_event["recent_snapshot_reuse"]) == {remainder_key}
    remainder_inventory_event = next(
        event
        for event in priority_events
        if event[0] == "scan_inventory_provider" and event[1][1] == remainder_key
    )
    assert remainder_inventory_event[1][5] is False

    # An explicit/manual scan always executes providers, even when a recent
    # snapshot timestamp is available.
    original_build_providers = globals()["build_providers"]
    try:
        globals()["build_providers"] = lambda: {
            priority_key: priority_provider,
            remainder_key: remainder_provider,
        }
        WinDevPilotApp._scan_worker(
            priority_scan_probe,
            80,
            {priority_key: False, remainder_key: True},
            False,
            {remainder_key: ([remainder_update], [remainder_package])},
            {},
            {remainder_key: time.monotonic()},
        )
    finally:
        globals()["build_providers"] = original_build_providers
    assert remainder_provider.discover_calls == remainder_provider.inventory_calls == 1

    unavailable_attempt_key = "missing-attempted-fixture"
    unavailable_attempt = UpdateItem(
        unavailable_attempt_key,
        "Unavailable attempted update",
        "Fixture.UnavailableAttempt",
        "1",
        "2",
        "fixture",
    )
    unavailable_scan_probe = object.__new__(WinDevPilotApp)
    unavailable_scan_probe._scan_cancel_requested = threading.Event()
    unavailable_scan_probe._provider_duration_hints = {}
    unavailable_scan_probe._provider_operation_locks = {
        remainder_key: threading.RLock()
    }
    unavailable_scan_probe._active_operation_items = {}
    unavailable_scan_probe._active_operation_results = []
    unavailable_scan_probe.events = queue.Queue()
    unavailable_scan_probe.logger = type(
        "UnavailableAttemptLogger", (), {"event": lambda *_args, **_kwargs: None}
    )()
    original_build_providers = globals()["build_providers"]
    try:
        globals()["build_providers"] = lambda: {remainder_key: remainder_provider}
        WinDevPilotApp._scan_worker(
            unavailable_scan_probe,
            79,
            {remainder_key: True},
            False,
            {},
            {
                unavailable_attempt.key: {
                    "item": item_diagnostic_fields(unavailable_attempt),
                    "result": {"success": True, "outcome": "updated"},
                }
            },
        )
    finally:
        globals()["build_providers"] = original_build_providers
    unavailable_events: list[tuple[str, Any]] = []
    while not unavailable_scan_probe.events.empty():
        unavailable_events.append(unavailable_scan_probe.events.get_nowait())
    unavailable_publish = next(
        event
        for event in unavailable_events
        if event[0] == "post_update_provider_updates"
    )
    assert unavailable_publish[1][1] == unavailable_attempt_key
    assert unavailable_publish[1][4] == "provider is disabled or unavailable"

    guarded_worker_probe = object.__new__(WinDevPilotApp)
    guarded_worker_probe.events = queue.Queue()
    guarded_worker_events: list[tuple[str, dict[str, Any]]] = []
    guarded_worker_probe.logger = type(
        "GuardedWorkerLogger",
        (),
        {
            "event": lambda _self, name, **fields: guarded_worker_events.append(
                (name, fields)
            )
        },
    )()

    def fail_guarded_worker() -> None:
        raise RuntimeError("guarded worker fixture")

    guarded_worker_probe._start_guarded_worker(
        fail_guarded_worker,
        name="wdp-self-test-worker",
        operation="scan",
        generation=7,
    )
    worker_event_name, worker_event_payload = guarded_worker_probe.events.get(timeout=2.0)
    assert worker_event_name == "worker_failed"
    assert worker_event_payload["operation"] == "scan"
    assert worker_event_payload["generation"] == 7
    assert worker_event_payload["exception_type"] == "RuntimeError"
    assert guarded_worker_events[0][0] == "state_worker_failed"
    interrupted_row = UpdateItem(
        "winget",
        "Interrupted",
        "Example.Interrupted",
        "1",
        "2",
        status="Updating…",
    )
    cleanup_probe = object.__new__(WinDevPilotApp)
    cleanup_probe._active_scan_generation = 0
    cleanup_probe.busy = False
    cleanup_probe._busy_kind = ""
    cleanup_probe.active_update_id = "interrupted-update"
    cleanup_probe.active_attempt_kind = "update"
    cleanup_probe._active_operation_original_statuses = {
        interrupted_row.key: "Ready to update"
    }
    partial_result = {
        "key": interrupted_row.key,
        "success": False,
        "outcome": "not-applicable",
    }
    cleanup_probe._active_operation_results = [partial_result]
    cleanup_probe._active_operation_items = {
        interrupted_row.key: dataclasses.replace(interrupted_row)
    }
    cleanup_events: list[tuple[str, dict[str, Any]]] = []
    remembered_partial: list[dict[str, Any]] = []
    refresh_reasons: list[str] = []
    notifications: list[str] = []
    cleanup_probe.logger = type(
        "CleanupLogger",
        (),
        {
            "event": lambda _self, name, **fields: cleanup_events.append(
                (name, fields)
            )
        },
    )()
    cleanup_probe._remember_attempt_outcomes = (
        lambda results: remembered_partial.extend(results)
    )
    cleanup_probe._scan_view_item = (
        lambda key: interrupted_row if key == interrupted_row.key else None
    )
    cleanup_probe._set_scan_view_item_status = (
        lambda key, status: setattr(interrupted_row, "status", status)
    )
    cleanup_probe._mark_scan_refresh_needed = refresh_reasons.append
    cleanup_probe._notify_user = (
        lambda message, **_kwargs: notifications.append(message)
    )
    WinDevPilotApp._finish_worker_failure(
        cleanup_probe,
        {
            "operation": "update",
            "generation": 0,
            "exception_type": "RuntimeError",
            "error": "synthetic interrupted update",
        },
    )
    assert interrupted_row.status == "Ready to update"
    assert remembered_partial == [partial_result]
    assert cleanup_probe.active_update_id == ""
    assert cleanup_probe.active_attempt_kind == ""
    assert not cleanup_probe._active_operation_original_statuses
    assert not cleanup_probe._active_operation_results
    assert not cleanup_probe._active_operation_items
    assert refresh_reasons and "rescan to confirm actual state" in refresh_reasons[-1]
    assert cleanup_events[-1][0] == "mutation_worker_failure_cleanup"
    assert notifications and "synthetic interrupted update" in notifications[-1]
    update_row = UpdateItem("winget", "Example", "Example.App", "1", "2")
    inventory_row = dataclasses.replace(
        update_row,
        available="1",
        selected=False,
        classification=CLASS_INVENTORY_ONLY,
    )
    active_done = dataclasses.replace(update_row, status="Updating…")
    active_queued = UpdateItem(
        "npm",
        "Queued tool",
        "@example/queued-tool",
        "3",
        "4",
        status="Queued",
    )
    scanned_queued = dataclasses.replace(active_queued, status="Ready")
    installed_done = dataclasses.replace(
        active_done,
        available=active_done.current,
        selected=False,
        status="Installed",
        classification=CLASS_INVENTORY_ONLY,
    )
    overlaid_updates, overlaid_packages = overlay_active_update_state(
        [scanned_queued],
        [installed_done],
        {
            active_done.key: active_done,
            active_queued.key: active_queued,
        },
        [
            {
                "key": active_done.key,
                "success": True,
                "cancelled": False,
                "warnings": [],
                "status_hint": "",
            }
        ],
        retain_missing_updates=True,
    )
    overlaid_by_key = {item.key: item for item in overlaid_updates}
    assert overlaid_by_key[active_done.key].current == "1"
    assert overlaid_by_key[active_done.key].available == "2"
    assert overlaid_by_key[active_done.key].status == "Reported updated — confirming…"
    assert not overlaid_by_key[active_done.key].selected
    assert overlaid_by_key[active_queued.key].status == "Queued"
    assert overlaid_by_key[active_queued.key].selected
    assert overlaid_packages[0].current == "1"
    assert overlaid_packages[0].status == "Reported updated — confirming…"
    without_retained, _packages = overlay_active_update_state(
        [],
        [],
        {active_done.key: active_done},
        [{"key": active_done.key, "success": True}],
        retain_missing_updates=False,
    )
    assert not without_retained

    class ScanViewStatusProbe:
        def __init__(self) -> None:
            self._last_scan_all_packages = True
            self._scan_view_items = {
                False: {update_row.key: update_row},
                True: {inventory_row.key: inventory_row},
            }
            self.items = self._scan_view_items[True]
            self.refreshed: list[UpdateItem] = []

        def _refresh_item_row(self, item: UpdateItem) -> None:
            self.refreshed.append(item)

    scan_view_probe = ScanViewStatusProbe()
    assert (
        WinDevPilotApp._scan_view_item(
            scan_view_probe,
            update_row.key,
            prefer_all_packages=False,
        )
        is update_row
    )
    visible_status_row = WinDevPilotApp._set_scan_view_item_status(
        scan_view_probe,
        update_row.key,
        "Updating…",
    )
    assert visible_status_row is inventory_row
    assert update_row.status == "Updating…"
    assert inventory_row.status == "Updating…"
    assert scan_view_probe.refreshed == [inventory_row]

    class PriorityValueProbe:
        def __init__(self) -> None:
            self.value = ""

        def set(self, value: str) -> None:
            self.value = value

    paint_update = dataclasses.replace(update_row, status="Updated", selected=True)
    paint_inventory = dataclasses.replace(
        inventory_row, status="Updated", selected=True
    )
    paint_probe = object.__new__(WinDevPilotApp)
    paint_probe._closing = False
    paint_probe._active_scan_generation = 92
    paint_probe._scan_active = True
    paint_probe._active_scan_origin = "post-update-verification"
    paint_probe._verification_update_id = "priority-paint-fixture"
    paint_probe._verification_results = {
        paint_update.key: {
            "item": item_diagnostic_fields(paint_update),
            "result": {"success": True, "outcome": "updated"},
        }
    }
    paint_probe._post_update_refresh_outcomes = {}
    paint_probe._scan_view_items = {
        False: {paint_update.key: paint_update},
        True: {paint_inventory.key: paint_inventory},
    }
    paint_probe._last_scan_all_packages = False
    paint_probe.items = paint_probe._scan_view_items[False]
    paint_probe._refresh_item_row = lambda _item: None
    paint_probe.summary_var = PriorityValueProbe()
    paint_probe._activity_base = ""
    paint_logs: list[str] = []
    paint_probe._append_log = paint_logs.append
    paint_probe.logger = type(
        "PriorityPaintFixtureLogger", (), {"event": lambda *_args, **_kwargs: None}
    )()
    WinDevPilotApp._apply_post_update_provider_updates(
        paint_probe,
        92,
        WingetProvider.key,
        "WinGet",
        [],
        "",
        0.25,
    )
    assert paint_update.status.startswith("No longer offered after attempt")
    assert paint_inventory.status.startswith("No longer offered after attempt")
    assert not paint_update.selected and not paint_inventory.selected
    assert paint_probe._post_update_refresh_outcomes == {
        paint_update.key: "resolved"
    }
    assert "1/1 attempted checked" in paint_probe.summary_var.value
    assert paint_logs and "Attempted-package refresh" in paint_logs[-1]
    recent_cache = _RecentWingetInventoryCache(ttl_seconds=5.0)
    refresh_token = recent_cache.begin_refresh("user")
    assert recent_cache.store("user", refresh_token, [{"Id": "Git.Git", "Version": "2.0"}])
    cached_rows = recent_cache.get("user")
    assert cached_rows == [{"Id": "Git.Git", "Version": "2.0"}], cached_rows
    cached_rows[0]["Id"] = "changed"
    assert recent_cache.get("user") == [{"Id": "Git.Git", "Version": "2.0"}]
    stale_token = recent_cache.begin_refresh("machine")
    recent_cache.invalidate()
    assert not recent_cache.store("machine", stale_token, [])
    expired_cache = _RecentWingetInventoryCache(ttl_seconds=-1.0)
    expired_token = expired_cache.begin_refresh("user")
    assert expired_cache.store("user", expired_token, [])
    assert expired_cache.get("user") is None
    scheduled = duration_prioritized_providers(
        [WingetProvider(), NpmProvider(), WindowsPowerShellProvider()],
        {"powershell5": 1.5, "winget": 1.2, "npm": 0.5},
    )
    assert [(index, provider.key) for index, provider in scheduled] == [
        (2, "powershell5"),
        (0, "winget"),
        (1, "npm"),
    ]
    snapshot_clock = 1_000.0
    recent_snapshot_ages_fixture = recent_untouched_provider_snapshot_ages(
        {"attempted", "recent", "expired", "missing"},
        {"attempted"},
        {
            "attempted": snapshot_clock - 1,
            "recent": snapshot_clock - 179.999,
            "expired": snapshot_clock - 180,
        },
        now=snapshot_clock,
    )
    assert set(recent_snapshot_ages_fixture) == {"recent"}
    assert math.isclose(recent_snapshot_ages_fixture["recent"], 179.999)
    assert recent_untouched_provider_snapshot_ages(
        {WingetProvider.key, MicrosoftStoreProvider.key, "recent"},
        {WingetProvider.key},
        {
            WingetProvider.key: snapshot_clock - 1,
            MicrosoftStoreProvider.key: snapshot_clock - 1,
            "recent": snapshot_clock - 1,
        },
        now=snapshot_clock,
    ) == {"recent": 1.0}
    assert set(
        recent_untouched_provider_snapshot_ages(
            {WingetProvider.key, MicrosoftStoreProvider.key},
            set(),
            {
                WingetProvider.key: snapshot_clock - 1,
                MicrosoftStoreProvider.key: snapshot_clock - 2,
            },
            now=snapshot_clock,
        )
    ) == {WingetProvider.key, MicrosoftStoreProvider.key}
    fixture = """\
Name                          Id                    Version Available Source
--------------------------------------------------------------------------
Git                           Git.Git               2.55.0  2.55.1    winget
Microsoft Teams Meeting Add   XP8BT8DW290MPQ        1.2      1.3       msstore
2 upgrades available.
"""
    rows = parse_fixed_table(fixture, ("Name", "Id", "Version", "Available", "Source"))
    assert len(rows) == 2, rows
    assert rows[0]["Id"] == "Git.Git", rows[0]
    assert rows[1]["Source"] == "msstore", rows[1]
    assert parse_winget_table_consensus(
        fixture,
        ("Name", "Id", "Version", "Available", "Source"),
        require_available=True,
    ) == rows
    touching_fixture = """\
Name        Id       Version Available Source
---------------------------------------------
LongNameHereGit.Git  2.55.0  2.55.1   winget
"""
    try:
        parse_winget_table_consensus(
            touching_fixture,
            ("Name", "Id", "Version", "Available", "Source"),
            require_available=True,
        )
    except ValueError:
        pass
    else:
        raise AssertionError("WinGet consensus parser trusted a token-boundary disagreement")
    structured_rows = parse_winget_structured_rows(
        json.dumps(
            {
                "Data": {
                    "Packages": [
                        {
                            "PackageName": "Git",
                            "PackageIdentifier": "Git.Git",
                            "InstalledVersion": "2.55.0",
                            "AvailableVersion": "2.55.1",
                            "SourceName": "winget",
                        }
                    ]
                }
            }
        ),
        updates=True,
    )
    assert structured_rows == [
        {
            "Name": "Git",
            "Id": "Git.Git",
            "Version": "2.55.0",
            "Available": "2.55.1",
            "Source": "winget",
        }
    ]
    try:
        parse_winget_structured_rows(
            '{"packages":[{"id":"Git.Git","version":"2","available":"3"}],'
            '"Packages":[]}',
            updates=True,
        )
    except ValueError:
        pass
    else:
        raise AssertionError("WinGet structured parser accepted duplicate case-folded keys")
    saved_capability_run_capture = globals()["run_capture"]
    winget_structured_output_arguments.cache_clear()
    try:
        globals()["run_capture"] = lambda *_args, **_kwargs: CommandResult(
            returncode=0,
            output="  --output  Select output format (json or text)",
            command=["winget", "list", "--help"],
        )
        assert winget_structured_output_arguments("list") == ("--output", "json")
    finally:
        globals()["run_capture"] = saved_capability_run_capture
        winget_structured_output_arguments.cache_clear()
    saved_fallback_run_capture = globals()["run_capture"]
    saved_structured_arguments = globals()["winget_structured_output_arguments"]
    fallback_commands: list[list[str]] = []

    def winget_schema_fallback_run(
        command: Sequence[str], *, timeout: int, **_kwargs: Any
    ) -> CommandResult:
        del timeout
        command_list = list(command)
        fallback_commands.append(command_list)
        if "--output" in command_list:
            return CommandResult(
                0,
                '{"schemaVersion":99,"results":[{"packageIdentifier":"Git.Git"}]}',
                command_list,
            )
        return CommandResult(0, fixture, command_list)

    try:
        globals()["run_capture"] = winget_schema_fallback_run
        globals()["winget_structured_output_arguments"] = lambda _command: (
            "--output",
            "json",
        )
        (
            fallback_result,
            fallback_rows,
            fallback_error,
            fallback_empty_proven,
        ) = WingetProvider()._read_package_rows(
            ["winget", "upgrade", "--disable-interactivity"],
            ("Name", "Id", "Version", "Available", "Source"),
            updates=True,
            timeout=30,
        )
        assert fallback_result.output == fixture
        assert fallback_rows == rows
        assert not fallback_error
        assert not fallback_empty_proven
        assert len(fallback_commands) == 2
        assert fallback_commands[0][-2:] == ["--output", "json"]
        assert fallback_commands[1] == ["winget", "upgrade", "--disable-interactivity"]
    finally:
        globals()["run_capture"] = saved_fallback_run_capture
        globals()["winget_structured_output_arguments"] = saved_structured_arguments

    try:
        globals()["winget_structured_output_arguments"] = lambda _command: (
            "--output",
            "json",
        )
        globals()["run_capture"] = lambda command, **_kwargs: CommandResult(
            0,
            '{"packages":[]}',
            list(command),
        )
        (
            _empty_result,
            empty_rows,
            empty_error,
            empty_proven,
        ) = WingetProvider()._read_package_rows(
            ["winget", "upgrade", "--disable-interactivity"],
            ("Name", "Id", "Version", "Available", "Source"),
            updates=True,
            timeout=30,
        )
        assert not empty_rows
        assert not empty_error
        assert empty_proven

        globals()["winget_structured_output_arguments"] = lambda _command: ()
        globals()["run_capture"] = lambda command, **_kwargs: CommandResult(
            0,
            "Réponse WinGet expérimentale sans tableau reconnu",
            list(command),
        )
        drift_rows, drift_error = WingetProvider()._upgrade_inventory("user")
        assert not drift_rows
        assert "explicit empty-result evidence" in drift_error

        globals()["run_capture"] = lambda command, **_kwargs: CommandResult(
            0,
            "",
            list(command),
        )
        silent_rows, silent_error = WingetProvider()._upgrade_inventory("user")
        assert not silent_rows
        assert "explicit empty-result evidence" in silent_error

        globals()["run_capture"] = lambda command, **_kwargs: CommandResult(
            0,
            "No installed package found matching input criteria.\r\n",
            list(command),
        )
        native_empty_rows, native_empty_error = WingetProvider()._upgrade_inventory(
            "user"
        )
        assert not native_empty_rows
        assert not native_empty_error

        globals()["run_capture"] = lambda command, **_kwargs: CommandResult(
            0,
            "Source refresh failed.\r\n"
            "No installed package found matching input criteria.\r\n",
            list(command),
        )
        mixed_empty_rows, mixed_empty_error = WingetProvider()._upgrade_inventory(
            "user"
        )
        assert not mixed_empty_rows
        assert "explicit empty-result evidence" in mixed_empty_error

        globals()["run_capture"] = lambda command, **_kwargs: CommandResult(
            WINGET_NO_APPLICATIONS_FOUND,
            "",
            list(command),
        )
        no_apps_rows, no_apps_error = WingetProvider()._upgrade_inventory("user")
        assert not no_apps_rows
        assert not no_apps_error
    finally:
        globals()["run_capture"] = saved_fallback_run_capture
        globals()["winget_structured_output_arguments"] = saved_structured_arguments
    digit_prefixed_fixture = """\
Name                          Id                    Version Available Source
--------------------------------------------------------------------------
123 Package Manager           Example.123           1.0     2.0       winget
1 package(s) are pinned and need to be explicitly upgraded.
"""
    digit_prefixed_rows = parse_fixed_table(
        digit_prefixed_fixture,
        ("Name", "Id", "Version", "Available", "Source"),
    )
    assert len(digit_prefixed_rows) == 1, digit_prefixed_rows
    assert digit_prefixed_rows[0]["Id"] == "Example.123", digit_prefixed_rows
    localized_fixture = """\
Nom                           Identifiant           Version  Disponible  Source
--------------------------------------------------------------------------
Git                           Git.Git               2.55.0   2.55.1      winget
"""
    localized_rows = parse_fixed_table(
        localized_fixture,
        ("Name", "Id", "Version", "Available", "Source"),
    )
    assert localized_rows == [
        {
            "Name": "Git",
            "Id": "Git.Git",
            "Version": "2.55.0",
            "Available": "2.55.1",
            "Source": "winget",
        }
    ], localized_rows
    segmented_localized_fixture = """\
Nom                           Identifiant           Version  Disponible  Source
---                           -----------           -------  ----------  ------
Git                           Git.Git               2.55.0   2.55.1      winget
"""
    assert parse_fixed_table(
        segmented_localized_fixture,
        ("Name", "Id", "Version", "Available", "Source"),
    ) == [
        {
            "Name": "Git",
            "Id": "Git.Git",
            "Version": "2.55.0",
            "Available": "2.55.1",
            "Source": "winget",
        }
    ]
    scoop_status_fixture = """\
Name     Installed Version Latest Version Missing Dependencies Info
----     ----------------- -------------- -------------------- ----
supabase 2.109.1           2.110.0
"""
    scoop_items = ScoopProvider._items_from_status_output(scoop_status_fixture)
    assert [
        (item.package_id, item.current, item.available) for item in scoop_items
    ] == [("supabase", "2.109.1", "2.110.0")], scoop_items
    with (
        patch.object(ScoopProvider, "_source_refresh_attempted_at", 0.0),
        patch.object(ScoopProvider, "_source_refresh_warning", ""),
        patch.object(time, "monotonic", return_value=1000.0) as scoop_clock,
        patch(f"{__name__}.run_capture", side_effect=[
            CommandResult(returncode=1, output="Refresh unavailable " + "x" * 400, command=["scoop", "update"]),
            CommandResult(returncode=0, output="Updated", command=["scoop", "update"]),
        ]) as scoop_refresh,
    ):
        scoop_probe = ScoopProvider()
        scoop_probe._refresh_sources_if_needed()
        refresh_warnings = list(scoop_probe.warnings)
        assert len(refresh_warnings) == 1 and "cached metadata" in refresh_warnings[0]
        assert len(refresh_warnings[0]) < 420
        scoop_probe.warnings.clear()  # Normal provider phases clear their warnings.
        scoop_clock.return_value = 1010.0
        scoop_probe._refresh_sources_if_needed()
        assert scoop_probe.warnings == refresh_warnings
        next_scoop_probe = ScoopProvider()
        next_scoop_probe._refresh_sources_if_needed()
        assert next_scoop_probe.warnings == refresh_warnings
        assert scoop_refresh.call_count == 1
        scoop_clock.return_value = 1000.0 + SCOOP_SOURCE_REFRESH_TTL_SECONDS
        next_scoop_probe.warnings.clear()
        next_scoop_probe._refresh_sources_if_needed()
        assert not next_scoop_probe.warnings and not ScoopProvider._source_refresh_warning
        scoop_probe.warnings.clear()
        scoop_probe._refresh_sources_if_needed()
        assert not scoop_probe.warnings and scoop_refresh.call_count == 2
        assert all(call.args == (["scoop", "update"],) for call in scoop_refresh.call_args_list)
    assert valid_package_id("@earendil-works/pi-coding-agent")
    assert valid_package_id("Notepad++.Notepad++")
    assert not valid_package_id("bad & calc.exe")
    assert not valid_package_id("pkg/../../status")
    assert not valid_package_id("pkg/./status")
    assert not valid_package_id("pkg//status")
    assert not valid_package_id("pkg/")
    provider_defaults = SettingsStore._defaults()["providers"]
    assert provider_defaults[PipProvider.key] is False
    assert provider_defaults[CargoProvider.key] is False
    original_program_files = os.environ.get("PROGRAMFILES")
    try:
        with tempfile.TemporaryDirectory(prefix="wdp-appx-location-") as appx_temp:
            program_files = Path(appx_temp)
            full_name = "Example.App_1.0.0.0_x64__publisher"
            appx_root = program_files / "WindowsApps" / full_name
            appx_root.mkdir(parents=True)
            os.environ["PROGRAMFILES"] = str(program_files)
            package_id = f"MSIX\\{full_name}"
            assert appx_package_install_location(package_id, "Example App") == appx_root
            appx_item = WindowsInstalledInventory.empty().enrich(
                UpdateItem(
                    provider="winget",
                    name="Example App",
                    package_id=package_id,
                    current="1.0.0.0",
                    available="1.0.0.0",
                    scope="user",
                    classification=CLASS_INVENTORY_ONLY,
                )
            )
            assert appx_item.installed_location == str(appx_root)
            assert appx_item.installed_technology == "msix"
            assert appx_item.installed_for == "current-user"
            assert appx_item.metadata_sources == ("appx-package-repository",)
            assert appx_item.metadata_confidence == "proven"
    finally:
        if original_program_files is None:
            os.environ.pop("PROGRAMFILES", None)
        else:
            os.environ["PROGRAMFILES"] = original_program_files
    assert valid_version("1!2.3.0-rc.1+build5")
    assert not valid_version("1.0 && calc")
    assert valid_provider_source("PSGallery")
    assert not valid_provider_source("https://example.invalid/api")
    assert treeview_wheel_rows_per_notch("\n tk::MouseWheel %W y %D -40.0 \n") == 3
    assert treeview_wheel_rows_per_notch(" %W yview scroll [expr {-%D / 120}] units ") == 1
    assert treeview_wheel_rows_per_notch("tk::MouseWheel %W y %D -12.0") == 0
    assert treeview_wheel_rows_per_notch("custom::Wheel %W %D") == 0
    for wheel_rate in (1, 3):
        for wheel_delta in (-120, -60, -40, -30, -15, -1, 0, 1, 15, 30, 40, 60, 120):
            wheel_remainder = total_rows = total_delta = 0
            for _ in range(120):
                rows, wheel_remainder = accumulated_wheel_rows(
                    wheel_delta, wheel_remainder, wheel_rate
                )
                total_rows += rows
                total_delta += wheel_delta
                assert abs(wheel_remainder) < 120
                assert -total_rows * 120 + wheel_remainder == total_delta * wheel_rate
            assert wheel_remainder == 0
            assert total_rows == -wheel_delta * wheel_rate
        wheel_remainder = total_rows = total_delta = 0
        for wheel_delta in (15, -30, 120, -60, -15, 40, -40, -120, 60, 30):
            rows, wheel_remainder = accumulated_wheel_rows(
                wheel_delta, wheel_remainder, wheel_rate
            )
            total_rows += rows
            total_delta += wheel_delta
            assert -total_rows * 120 + wheel_remainder == total_delta * wheel_rate
            assert abs(wheel_remainder) < 120
    assert search_match_rank("win", ((0, "WinMark"), (1, "pkg.id"), (2, "WinGet"))) == (0, 0)
    assert search_match_rank("win", ((0, "Tool"), (1, "Acme.WinTool"), (2, "WinGet"))) == (
        1,
        5,
    )
    assert search_match_rank("win", ((0, "Tool"), (1, "Acme.Tool"), (2, "WinGet"))) == (2, 0)
    dotnet_provider_field = ((2, ".NET global tools"),)
    assert search_match_rank(".net", dotnet_provider_field) == (2, 0)
    assert search_match_rank("net global tools", dotnet_provider_field) == (2, 0)
    assert parse_package_filter("port") == ("port", ())
    assert parse_package_filter("http://example.test") == ("http://example.test", ())
    assert parse_package_filter("Provider:NPM scope:USER Visual Studio") == (
        "Visual Studio", (("provider", "npm"), ("scope", "user")),
    )
    assert parse_package_filter("provider:store") == ("", (("provider", "msstore"),))
    search_probe = object.__new__(WinDevPilotApp)
    search_probe.providers = {
        "npm": SimpleNamespace(label="npm global packages"),
        "winget": SimpleNamespace(label="WinGet"),
        "portable": SimpleNamespace(label="Portable apps"),
        "msstore": SimpleNamespace(label="Microsoft Store"),
    }
    search_probe.process_is_admin = True  # is:admin means the package requirement.
    search_probe.settings = SimpleNamespace(data={"attempt_holds": {}})
    npm_search_item = UpdateItem("npm", "ESLint", "eslint", "1", "2")
    incidental_npm = UpdateItem("winget", "npm Helper", "Example.npm", "1", "2",
                               scope="machine", requires_admin=True)
    portable_search_item = UpdateItem("portable", "Rufus", "rufus", "1", "2", selected=False)
    for search_item, query, expected in (
        (npm_search_item, "npm", True), (incidental_npm, "npm", True),
        (npm_search_item, "provider:npm", True), (incidental_npm, "provider:npm", False),
        (npm_search_item, "PROVIDER:NPM scope:user eslint", True),
        (npm_search_item, "provider:npm scope:machine", False),
        (npm_search_item, "provider:npm is:admin", False),
        (incidental_npm, "scope:machine is:admin", True),
        (portable_search_item, "port", True), (portable_search_item, "is:portable", True),
        (portable_search_item, "provider:portable ruf", True),
        (portable_search_item, "is:selected", False),
        (npm_search_item, "is:selected", True),
        (npm_search_item, "provider:np", False),
        (npm_search_item, "provider:", False),
        (npm_search_item, "is:seleted", False),
        (npm_search_item, "scope:", False),
        (npm_search_item, "is:", False),
        (npm_search_item, "provider:npm provider:winget", False),
    ):
        assert search_probe._matches_filter(search_item, query) is expected, query
    assert search_probe._filter_rank(npm_search_item, "provider:npm eslint") == (0, 0)
    assert search_probe._filter_rank(incidental_npm, "npm") == (0, 0)
    store_search_item = UpdateItem("msstore", "Example", "Store.ID", "1", "2")
    assert search_probe._matches_filter(store_search_item, "provider:store")
    steam_search_item = UpdateItem(
        "winget", "Example Game", r"ARP\Machine\X64\Steam App 123", "1", "",
        classification=CLASS_INVENTORY_ONLY,
    )
    assert search_probe._matches_filter(steam_search_item, "provider:steam")
    assert not search_probe._matches_filter(steam_search_item, "provider:winget")
    npm_search_item.status = "Unrelated text mentioning held"
    assert not search_probe._matches_filter(npm_search_item, "is:held")
    search_probe.settings.data["attempt_holds"][npm_search_item.candidate_key] = {"outcome": "failed"}
    assert search_probe._matches_filter(npm_search_item, "is:held provider:npm")
    assert not search_probe._matches_filter(dataclasses.replace(npm_search_item, available="3"), "is:held")
    search_probe.settings.data["attempt_holds"][incidental_npm.candidate_key] = {
        "item": {"provider": "winget"}, "strategy_revision": WINGET_ATTEMPT_STRATEGY_REVISION - 1,
    }
    assert not search_probe._matches_filter(incidental_npm, "is:held")
    # Checkbox changes already use _refresh_item_row's filter-membership check.
    search_probe.items = {npm_search_item.key: npm_search_item, incidental_npm.key: incidental_npm}
    search_probe.search_var = Mock()
    search_probe.search_var.get.return_value = "is:selected"
    search_probe.tree = Mock()
    search_probe.tree.exists.return_value = True
    search_probe.tree.selection.return_value = (npm_search_item.key,)
    search_probe._selection_touched_keys = set()
    search_probe._sort_state = None
    search_probe._schedule_rebuild_tree = Mock()
    search_probe._refresh_scan_summary_counts = Mock()
    search_probe._toggle_tree_rows_like(npm_search_item.key)
    assert not npm_search_item.selected and incidental_npm.selected
    search_probe._schedule_rebuild_tree.assert_called_once()
    search_probe.tree.item.assert_not_called()
    # Bulk helpers remain scoped to matching, eligible rows.
    search_probe.busy = False
    search_probe._rebuild_tree = Mock()
    search_probe.search_var.get.return_value = "provider:npm"
    search_probe.select_all()
    assert npm_search_item.selected and incidental_npm.selected
    search_probe.select_none()
    assert not npm_search_item.selected and incidental_npm.selected
    assert (
        _shared_shortcut_brand(
            "Microsoft.DotNet.Runtime.8",
            "Microsoft .NET Runtime 8",
            _icon_match_words("Microsoft .NET Runtime 8"),
        )
        == ""
    )
    assert (
        _shared_shortcut_brand(
            "Python.Python.3.12",
            "Python 3.12",
            _icon_match_words("Python 3.12"),
        )
        == "python"
    )
    assert not _shortcut_prefix_is_distinctive(len("microsoft"), "microsoft")
    assert _shortcut_prefix_is_distinctive(len("microsoftvisual"), "microsoft")
    with tempfile.TemporaryDirectory(prefix="wdp-run-route-") as run_route_temp:
        run_route_root = Path(run_route_temp)
        steam_shortcut = run_route_root / "Example Game.url"
        steam_shortcut.write_text(
            "[InternetShortcut]\nURL=steam://rungameid/91232983\n",
            encoding="utf-8",
        )
        shortcut_entries = (
            (
                steam_shortcut,
                _icon_match_text(steam_shortcut.stem),
                "games",
                frozenset(_icon_match_words(steam_shortcut.stem)),
            ),
        )
        assert start_menu_shortcut_launch_path(
            "Steam.91232983",
            "Example Game",
            entries=shortcut_entries,
        ) == steam_shortcut
        shortcut_item = UpdateItem(
            provider="winget",
            name="Example Game",
            package_id="Steam.91232983",
            current="1",
            available="1",
        )
        with patch(f"{__name__}.os.startfile", create=True) as startfile:
            activate_app_route(AppRunRoute("shortcut", steam_shortcut))
            startfile.assert_called_once_with(steam_shortcut)
        ambiguous_entries = shortcut_entries + (
            (
                run_route_root / "Example Game.lnk",
                _icon_match_text("Example Game"),
                "games",
                frozenset(_icon_match_words("Example Game")),
            ),
        )
        assert not start_menu_shortcut_launch_path(
            "Steam.91232983",
            "Example Game",
            entries=ambiguous_entries,
        )
        app_id_record = {
            "full_name": "Example.App_1.0.0.0_x64__123456789abcd",
            "family": "Example.App_123456789abcd",
            "launch_ids": ["App", "App", "Helper", "bad!id", "../bad"],
        }
        assert windows_package_launch_ids(app_id_record) == (
            "Example.App_123456789abcd!App", "Example.App_123456789abcd!Helper",
        )
        assert not windows_package_launch_ids({**app_id_record, "family": "Other.App_123456789abcd"})
        assert not windows_package_launch_ids({**app_id_record, "launch_ids": "App"})
        desktop_full_name = "Claude_1.0.0.0_x64__pzs8sxrjxfjjc"
        desktop_root = run_route_root / desktop_full_name
        desktop_root.mkdir()
        desktop_manifest = desktop_root / "AppxManifest.xml"
        desktop_manifest.write_text(
            '<Package xmlns="urn:fixture"><Identity Name="Claude" Version="1.0.0.0" />'
            '<Applications><Application Id="Claude"><VisualElements /></Application>'
            '<Application Id="Helper"><VisualElements AppListEntry="none" /></Application>'
            '<Application Id="Background" /></Applications></Package>', encoding="utf-8",
        )
        desktop_item = dataclasses.replace(
            shortcut_item, name="Claude (Desktop app)", package_id="Anthropic.Claude", current="1.0.0.0",
        )
        registered_entries = ((desktop_full_name, "Claude", desktop_root),)
        with patch(f"{__name__}._installed_appx_repository_entries", return_value=registered_entries):
            assert registered_launch_package("winget", "Anthropic.Claude", "1.0.0.0") == (desktop_full_name, desktop_root)
            assert registered_launch_package("winget", "MSIX\\" + desktop_full_name) == (desktop_full_name, desktop_root)
            assert not registered_launch_package("winget", "Anthropic.Claude", "2.0.0.0")
            assert not registered_launch_package("winget", "Anthropic.ClaudeCode", "1.0.0.0")
            assert not registered_launch_package("npm", "Anthropic.Claude", "1.0.0.0")
            assert not registered_launch_package("winget", "Other.Claude", "1.0.0.0")
            expected_desktop_route = AppRunRoute("app-id", "Claude_pzs8sxrjxfjjc!Claude")
            assert app_run_routes(desktop_item) == (expected_desktop_route,)
            with patch(f"{__name__}.appx_manifest_logo_path", return_value=None):
                enriched = enrich_appx_package_identity(dataclasses.replace(desktop_item))
                assert enriched.launch_app_ids == (expected_desktop_route.target,)
                assert enriched.installed_location == str(desktop_root)
                assert enriched.installed_technology == "msix"
                assert enriched.provider == desktop_item.provider and enriched.source == desktop_item.source
                assert "microsoft-store-signature" not in enriched.metadata_sources
                existing_exe = dataclasses.replace(desktop_item, installed_technology="exe")
                assert not enrich_appx_package_identity(existing_exe).launch_app_ids
        with patch(f"{__name__}._installed_appx_repository_entries", return_value=registered_entries * 2):
            assert not registered_launch_package("winget", "Anthropic.Claude", "1.0.0.0")
        with patch(f"{__name__}._installed_appx_repository_entries", return_value=((
            desktop_full_name.replace("pzs8sxrjxfjjc", "123456789abcd"), "Claude", desktop_root,
        ),)):
            assert not registered_launch_package("winget", "Anthropic.Claude", "1.0.0.0")
        desktop_stat = desktop_manifest.stat()
        assert _registered_manifest_launch_ids(desktop_full_name, desktop_manifest, desktop_stat.st_mtime_ns, desktop_stat.st_size) == ("Claude_pzs8sxrjxfjjc!Claude",)
        assert not _registered_manifest_launch_ids(desktop_full_name.replace("1.0.0.0", "2.0.0.0"), desktop_manifest, desktop_stat.st_mtime_ns, desktop_stat.st_size)
        assert not _registered_manifest_launch_ids(desktop_full_name, desktop_manifest, desktop_stat.st_mtime_ns, 5 * 1024 * 1024)
        app_id_item = dataclasses.replace(
            shortcut_item, classification=CLASS_INVENTORY_ONLY, selected=False,
            metadata_sources=("windows-packagemanager",),
            launch_app_ids=("Example.App_123456789abcd!App",),
        )
        app_id_route = AppRunRoute("app-id", app_id_item.launch_app_ids[0])
        assert app_run_routes(app_id_item) == (app_id_route,)
        assert app_local_path_details(app_id_item) == (("Windows application ID", app_id_route.target),)
        cached_item = json.loads(json.dumps(dataclasses.asdict(app_id_item)))
        assert InstalledInventoryStore._item_from_json(cached_item, {"winget"}).launch_app_ids == app_id_item.launch_app_ids
        del cached_item["launch_app_ids"]
        assert InstalledInventoryStore._item_from_json(cached_item, {"winget"}).launch_app_ids == ()
        for field in ("installed_timestamp", "installed_timestamp_precision", "installed_registration_changed_at", "installed_registration_changed_at_precision"):
            del cached_item[field]
        assert InstalledInventoryStore._item_from_json(cached_item, {"winget"}).launch_app_ids == ()
        with patch(f"{__name__}.os.startfile", create=True) as startfile:
            activate_app_route(app_id_route)
            startfile.assert_called_once_with("shell:AppsFolder\\Example.App_123456789abcd!App")
        with patch(f"{__name__}.activate_app_route") as activate:
            launch_probe = SimpleNamespace(
                busy=True, _busy_kind="scan", summary_var=Mock(), logger=Mock(),
                _notify_user=Mock(), _append_log=Mock(),
            )
            WinDevPilotApp._launch_item(launch_probe, app_id_item)
            activate.assert_called_once_with(app_id_route)
            launch_probe.summary_var.set.assert_not_called()
            for kind in ("update", "selected-preflight", "portable-scan", "uninstall"):
                launch_probe._busy_kind = kind
                WinDevPilotApp._launch_item(launch_probe, app_id_item)
            assert activate.call_count == 1
            launch_probe.busy = False
            WinDevPilotApp._launch_item(launch_probe, app_id_item, AppRunRoute("app-id", "changed"))
            assert activate.call_count == 1
            assert launch_probe._notify_user.called
        keyboard_probe = SimpleNamespace(
            tree=Mock(), search_entry=object(), items={"visible": app_id_item},
            _launch_item=Mock(), _notify_user=Mock(),
            focused_or_selected_item=Mock(return_value=app_id_item),
        )
        keyboard_probe.tree.get_children.return_value = ("visible",)
        assert WinDevPilotApp._run_from_keyboard(
            keyboard_probe, SimpleNamespace(widget=keyboard_probe.search_entry),
        ) == "break"
        keyboard_probe._launch_item.assert_called_once_with(app_id_item)
        keyboard_probe.tree.get_children.return_value = ("visible", "other")
        WinDevPilotApp._run_from_keyboard(keyboard_probe, SimpleNamespace(widget=keyboard_probe.search_entry))
        keyboard_probe.tree.focus.return_value = "hidden"
        WinDevPilotApp._run_from_keyboard(keyboard_probe, SimpleNamespace(widget=keyboard_probe.tree))
        assert keyboard_probe._launch_item.call_count == 1
        keyboard_probe.tree.focus.return_value = "visible"
        WinDevPilotApp._run_from_keyboard(keyboard_probe, SimpleNamespace(widget=keyboard_probe.tree))
        assert keyboard_probe._launch_item.call_count == 2
        first_link = run_route_root / "First.lnk"
        second_link = run_route_root / "Second.lnk"
        executable = run_route_root / "bin" / "example.exe"
        script_host = run_route_root / "cmd.exe"
        script = run_route_root / "scripts" / "start.cmd"
        executable.parent.mkdir()
        script.parent.mkdir()
        for fixture in (first_link, second_link, executable, script_host, script):
            fixture.touch()
        equivalent_entries = tuple(
            (path, _icon_match_text("Example"), "", frozenset())
            for path in (first_link, second_link)
        )
        details = WindowsShortcutDetails(str(executable), "--one", str(executable.parent))
        with patch(f"{__name__}._cached_launch_shortcut", return_value=details):
            assert start_menu_shortcut_launch_paths("Example", "Example", entries=equivalent_entries) == (first_link,)
        with patch(f"{__name__}._cached_launch_shortcut", side_effect=[details, dataclasses.replace(details, arguments="--two")]):
            assert len(start_menu_shortcut_launch_paths("Example", "Example", entries=equivalent_entries)) == 2
        with patch(f"{__name__}._cached_launch_shortcut", side_effect=[details, dataclasses.replace(details, working_directory=str(run_route_root))]):
            assert len(start_menu_shortcut_launch_paths("Example", "Example", entries=equivalent_entries)) == 2
        _cached_launch_shortcut.cache_clear()
        with patch(f"{__name__}.read_windows_shortcut", return_value=details) as read_link:
            for _ in range(2):
                assert start_menu_shortcut_launch_paths("Example", "Example", entries=equivalent_entries) == (first_link,)
            assert read_link.call_count == 2  # Once per file, not per menu opening.
            first_link.write_bytes(b"changed shortcut fixture")
            start_menu_shortcut_launch_paths("Example", "Example", entries=equivalent_entries)
            assert read_link.call_count == 3
        _cached_launch_shortcut.cache_clear()
        with patch(f"{__name__}.portable_pe_subsystem", return_value=3), patch(f"{__name__}.subprocess.Popen") as popen:
            activate_app_route(AppRunRoute("executable", executable))
            assert popen.call_args.kwargs["creationflags"] == subprocess.CREATE_NEW_CONSOLE
            assert "/d /v:off /k" in popen.call_args.args[0]
            assert "stdout" not in popen.call_args.kwargs
            try:
                activate_app_route(AppRunRoute("executable", run_route_root / "%PATH%.exe"))
            except OSError:
                pass
            else:
                raise AssertionError("Console route admitted command expansion")
            assert popen.call_count == 1
        folder_item = dataclasses.replace(
            shortcut_item, name="Example", package_id="Vendor.Example",
            installed_location=str(executable.parent), metadata_confidence="proven",
            metadata_sources=("arp-uninstall",),
        )
        with patch(f"{__name__}._launch_executable_identity", return_value=("example", "example", "exampleexe")):
            assert installed_folder_launch_paths(folder_item) == (executable.resolve(),)
            assert not installed_folder_launch_paths(dataclasses.replace(folder_item, metadata_confidence=""))
            assert not installed_folder_launch_paths(dataclasses.replace(folder_item, name="Other", package_id="Vendor.Other"))
        with patch(f"{__name__}._launch_executable_identity", return_value=()):
            assert not installed_folder_launch_paths(folder_item)
        with patch(f"{__name__}._launch_executable_identity", return_value=("other", "backgroundhelper", "exampleexe")):
            assert not installed_folder_launch_paths(dataclasses.replace(folder_item, name="Other", package_id="Vendor.Other"))
        shortcut_map = {
            first_link: WindowsShortcutDetails(str(second_link)),
            second_link: WindowsShortcutDetails(str(executable)),
        }

        def fixture_shortcut_reader(path: Path) -> WindowsShortcutDetails | None:
            return shortcut_map.get(path)

        assert shortcut_terminal_target(
            first_link, read_shortcut=fixture_shortcut_reader
        ) == executable.resolve()
        assert app_containing_target(
            shortcut_item,
            AppRunRoute("shortcut", first_link.resolve()),
            read_shortcut=fixture_shortcut_reader,
        ) == executable.resolve()
        resolved_shortcut_route = AppRunRoute("shortcut", first_link.resolve())
        assert app_shortcut_path(resolved_shortcut_route) == first_link.resolve()
        local_path_fields = app_local_path_details(
            shortcut_item,
            resolved_shortcut_route,
            read_shortcut=fixture_shortcut_reader,
        )
        assert local_path_fields == (
            ("Launch shortcut", str(first_link.resolve())),
            ("Resolved local target", str(executable.resolve())),
            ("Containing folder", str(executable.parent.resolve())),
        )
        shortcut_map[second_link.resolve()] = WindowsShortcutDetails(str(first_link))
        shortcut_map[first_link.resolve()] = shortcut_map.pop(first_link)
        assert shortcut_terminal_target(first_link, read_shortcut=fixture_shortcut_reader) is None
        script_shortcut = run_route_root / "Script.lnk"
        script_shortcut.touch()
        script_details = WindowsShortcutDetails(
            str(script_host),
            arguments=f'/d /c "{script}" --quiet',
            working_directory=str(run_route_root),
        )
        assert shortcut_terminal_target(
            script_shortcut,
            read_shortcut=lambda _path: script_details,
        ) == script.resolve()
        assert (
            shortcut_terminal_target(
                script_shortcut,
                read_shortcut=lambda _path: dataclasses.replace(
                    script_details, arguments="/d /c echo no-local-target"
                ),
            )
            is None
        )
    with tempfile.TemporaryDirectory(prefix="wdp-graphics-clean-") as graphics_temp:
        graphics_root = Path(graphics_temp)
        cache_root = graphics_root / "icon-cache"
        cache_root.mkdir()
        retained_files = [
            graphics_root / INSTALLED_INVENTORY_CACHE_FILENAME,
            graphics_root / PORTABLE_CACHE_FILENAME,
            graphics_root / "settings.json",
            graphics_root / "session.log",
            graphics_root / "original.png",
            cache_root / "unrelated.txt",
        ]
        nested = cache_root / "rawicon-folder.png"
        nested.mkdir()
        retained_files.append(nested / "keep.txt")
        for path in retained_files:
            path.write_bytes(b"installation-date and history fixture: unchanged")
        generated_files = [
            cache_root / ICON_CATALOG_FILENAME,
            cache_root / f"{RAW_ICON_CACHE_PREFIX}fixture.png",
            cache_root / f"{DISPLAY_ICON_CACHE_PREFIX}fixture.json",
            cache_root / f"{PROVIDER_ICON_CACHE_PREFIX}fixture.png",
            cache_root / f".{RAW_ICON_CACHE_PREFIX}fixture.png.1.tmp",
        ]
        for path in generated_files:
            path.write_bytes(b"generated cache fixture")
        enumeration_complete = False
        original_scandir = os.scandir
        cleanup_unlink = Path.unlink

        @contextlib.contextmanager
        def tracked_cache_enumeration(path: Path):
            nonlocal enumeration_complete
            with original_scandir(path) as entries:
                def tracked_entries():
                    nonlocal enumeration_complete
                    yield from entries
                    enumeration_complete = True
                yield tracked_entries()

        def unlink_after_enumeration(path: Path, *args: Any, **kwargs: Any) -> None:
            assert enumeration_complete, "deletion must follow complete directory enumeration"
            cleanup_unlink(path, *args, **kwargs)

        with patch.dict(globals(), icon_cache_dir=lambda: cache_root), patch.object(
            os, "scandir", tracked_cache_enumeration
        ), patch.object(Path, "unlink", unlink_after_enumeration):
            assert clear_generated_icon_cache_files() == (len(generated_files), 2)
        assert all(not path.exists() for path in generated_files)
        assert all(path.read_bytes() == b"installation-date and history fixture: unchanged"
                   for path in retained_files)
        generated_files[1].touch()
        original_unlink = Path.unlink

        def inaccessible_cache_file(path: Path, *args: Any, **kwargs: Any) -> None:
            if path == generated_files[1]:
                raise PermissionError("fixture")
            original_unlink(path, *args, **kwargs)

        with patch.dict(globals(), icon_cache_dir=lambda: cache_root), patch.object(
            Path, "unlink", inaccessible_cache_file
        ):
            assert clear_generated_icon_cache_files() == (0, 3)
        assert generated_files[1].exists()
        with patch.dict(globals(), icon_cache_dir=lambda: graphics_root / "absent"):
            assert clear_generated_icon_cache_files() == (0, 0)
        with patch.dict(globals(), icon_cache_dir=lambda: cache_root), patch.object(
            Path, "lstat", return_value=Mock(st_mode=stat.S_IFDIR, st_file_attributes=0x400)
        ), patch.object(os, "scandir", side_effect=AssertionError("must not traverse a junction")):
            try:
                clear_generated_icon_cache_files()
            except OSError:
                pass
            else:
                raise AssertionError("graphics cleanup accepted a reparse root")

    clean_probe = object.__new__(WinDevPilotApp)
    clean_probe.root = object()
    clean_probe.messagebox = Mock()
    for flag in ("_closing", "busy", "_scan_active", "_portable_scan_active", "_cache_clear_inflight"):
        setattr(clean_probe, flag, False)
    with patch.object(clean_probe, "_clear_graphics_cache") as clear_graphics:
        clean_probe.messagebox.askokcancel.return_value = False
        clean_probe._clean_graphics_cache_from_ui()
        clear_graphics.assert_not_called()
        confirmation = clean_probe.messagebox.askokcancel.call_args
        assert "Installation-date metadata will not be deleted" in confirmation.args[1]
        assert confirmation.kwargs["default"] == "cancel"
        assert confirmation.kwargs["parent"] is clean_probe.root
        clean_probe.messagebox.askokcancel.return_value = True
        clean_probe._clean_graphics_cache_from_ui()
        clear_graphics.assert_called_once()
    for flag in ("_closing", "busy", "_scan_active", "_portable_scan_active", "_cache_clear_inflight"):
        setattr(clean_probe, flag, True)
        clean_probe.messagebox.reset_mock()
        clean_probe._clean_graphics_cache_from_ui()
        clean_probe._clear_graphics_cache()  # Recheck before changing any state.
        clean_probe.messagebox.askokcancel.assert_not_called()
        setattr(clean_probe, flag, False)

    # Run cleanup against a real coordinator and real temporary files. Control
    # only the rendering boundary so an active job cannot finish before the test.
    for renderer_times_out in (False, True):
        with tempfile.TemporaryDirectory(prefix="wdp-active-render-clean-") as clean_temp:
            clean_root = Path(clean_temp)
            clean_cache = clean_root / "icons"
            clean_cache.mkdir()
            late_artwork = clean_cache / f"{RAW_ICON_CACHE_PREFIX}active.png"
            late_artwork.write_bytes(b"old generated artwork")
            kept_history = clean_root / "settings.json"
            kept_history.write_bytes(b"installation history fixture")
            render_started = threading.Event()
            release_render = threading.Event()
            cleanup_waiting = threading.Event()
            render_results: queue.Queue[tuple[bool, bool, str]] = queue.Queue()
            clean_renderer = IconRenderCoordinator()
            active_clean_probe = object.__new__(WinDevPilotApp)
            active_clean_probe._icon_resolution_generation = 0
            active_clean_probe._icon_sort_colors = {}
            active_clean_probe._icon_sort_active = False
            for flag in ("_closing", "busy", "_scan_active", "_portable_scan_active", "_cache_clear_inflight"):
                setattr(active_clean_probe, flag, False)
            for generation_field in (
                "_icon_prepare_generation", "_warm_icon_restore_generation",
                "_icon_catalog_load_generation", "_icon_catalog_write_generation",
            ):
                setattr(active_clean_probe, generation_field, 0)
            for collection in (
                "_icon_catalog_entries", "_icon_catalog_blobs", "_icon_catalog_valid_paths",
                "_icon_catalog_list_display_paths", "_icon_catalog_decode_queue",
                "_provider_icon_images", "_package_icon_images", "_details_icon_images",
                "_package_gallery_attempts", "_package_gallery_misses",
                "_package_icon_misses", "_package_icon_ready", "_item_icon_source_cache",
                "_tree_icon_kind", "_icon_prepare_inflight", "_details_icon_callbacks",
                "_icon_gallery_photo_decode_queue", "_icon_gallery_photo_decode_pending",
                "_icon_gallery_blit_cache", "_icon_showcase_cache", "_icon_showcase_inflight",
            ):
                setattr(active_clean_probe, collection, {})
            for method in (
                "_refresh_secondary_actions_menu", "_cancel_after_id", "_reset_ready_icon_memory_load",
                "_reset_background_icon_sweep", "_reset_background_details_icon_sweep",
                "_append_log", "_schedule_visible_icon_hydration", "_schedule_background_icon_sweep",
                "_notify_user",
            ):
                setattr(active_clean_probe, method, Mock())
            active_clean_probe.icon_renderer = clean_renderer
            active_clean_probe._icon_catalog_write_lock = threading.Lock()
            active_clean_probe.events = queue.Queue()
            active_clean_probe.logger = Mock()
            active_clean_probe.tree = Mock()
            active_clean_probe.tree.get_children.return_value = ()
            active_clean_probe.settings = Mock(data={"package_history": {"fixture": "kept"}})

            def controlled_render(request: IconRenderRequest) -> tuple[bool, bool, str]:
                render_started.set()
                if not release_render.wait(10.0):
                    return False, False, "test render was not released"
                request.raw_path.write_bytes(b"late generated artwork")
                return True, False, ""

            real_wait_idle = clean_renderer.wait_idle

            def observed_cleanup_wait(timeout: float) -> bool:
                cleanup_waiting.set()
                return False if renderer_times_out else real_wait_idle(timeout)

            render_caller = threading.Thread(target=lambda: render_results.put(clean_renderer.prepare(
                late_artwork, late_artwork, 32, small_shell_icon=True,
                fit_art_at_scale=None, generation=0, priority=10,
            )), daemon=True)
            cleanup_started = cleanup_result_received = False
            with (
                patch.object(clean_renderer, "_execute_with_recovery", side_effect=controlled_render),
                patch.object(clean_renderer, "wait_idle", side_effect=observed_cleanup_wait),
                patch(f"{__name__}.icon_cache_dir", return_value=clean_cache),
                patch(f"{__name__}.invalidate_start_menu_shortcut_index"),
            ):
                try:
                    render_caller.start()
                    assert render_started.wait(5.0)
                    active_clean_probe._clear_graphics_cache()
                    cleanup_started = True
                    assert active_clean_probe._icon_prepare_generation == 1
                    assert cleanup_waiting.wait(5.0)
                    assert late_artwork.read_bytes() == b"old generated artwork"
                    if not renderer_times_out:
                        release_render.set()
                    event, payload = active_clean_probe.events.get(timeout=10.0)
                    cleanup_result_received = True
                    if renderer_times_out:
                        assert event == "worker_failed" and payload["operation"] == "cache-clear"
                        assert "cached files were not deleted" in payload["error"]
                        assert late_artwork.exists()
                        active_clean_probe._finish_worker_failure(payload)
                        release_render.set()
                    else:
                        assert event == "caches_cleared" and payload == (1, 0)
                        active_clean_probe._finish_cache_clear(*payload)
                    render_caller.join(timeout=5.0)
                    assert not render_caller.is_alive()
                    assert render_results.get_nowait() == (False, False, "render request was superseded")
                    # Even a previously queued successful UI completion is stale.
                    active_clean_probe._finish_icon_prepare(
                        "fixture-row", 32, ("fixture-row", 32, "light"), True, False,
                        late_artwork, 0, "",
                    )
                    assert not active_clean_probe._item_icon_source_cache
                    assert not active_clean_probe._package_icon_ready
                    assert not active_clean_probe._cache_clear_inflight
                    assert late_artwork.exists() == renderer_times_out
                    assert kept_history.read_bytes() == b"installation history fixture"
                    assert active_clean_probe.settings.data == {"package_history": {"fixture": "kept"}}
                    active_clean_probe.settings.save.assert_not_called()
                finally:
                    # Keep the temporary cache routing installed until every
                    # worker has returned, even when an assertion fails.
                    release_render.set()
                    if render_caller.ident is not None:
                        render_caller.join(timeout=5.0)
                    try:
                        if cleanup_started and not cleanup_result_received:
                            active_clean_probe.events.get(timeout=10.0)
                    finally:
                        clean_renderer.shutdown(timeout=2.0)
            assert not clean_renderer._thread.is_alive()

    with tempfile.TemporaryDirectory(prefix="wdp-portable-artwork-") as artwork_temp:
        artwork_root = Path(artwork_temp)
        executable = artwork_root / "example.exe"
        assert choose_portable_icon_source(executable) == executable
        executable.touch()
        # Keep size preference, directory names, and the full-filename tie-break.
        assets = artwork_root / "ASSETS"
        assets.mkdir()
        small_art = assets / "app.png"
        larger_art = assets / "logo.ico"
        small_art.write_bytes(b"12")
        larger_art.write_bytes(b"1234")
        assert choose_portable_icon_source(executable) == larger_art
        small_art.write_bytes(b"1234")
        assert choose_portable_icon_source(executable) == small_art
        exact_art = artwork_root / "example.PNG"
        exact_art.write_bytes(b"1")
        assert choose_portable_icon_source(executable) == exact_art
        assert choose_portable_icon_source(executable, preferred_icon=larger_art) == larger_art
        tie_root = artwork_root / "tie"
        tie_root.mkdir()
        for filename in ("a.png", "a-extra.png"):
            (tie_root / filename).write_bytes(b"same size")
        assert choose_portable_icon_source(tie_root / "absent.exe") == tie_root / "a-extra.png"
        with patch.object(os, "scandir", side_effect=PermissionError("fixture")):
            assert choose_portable_icon_source(executable) == executable

    with tempfile.TemporaryDirectory(prefix="wdp-nearby-artwork-") as artwork_temp:
        artwork_root = Path(artwork_temp)
        executable = artwork_root / "bin" / "example.exe"
        executable.parent.mkdir()
        executable.touch()
        current_icon = artwork_root / "registered.ico"
        current_icon.write_bytes(
            b"\0\0\1\0\1\0"
            + bytes((32, 32, 0, 0))
            + struct.pack("<HHII", 1, 32, 4, 22)
            + b"data"
        )
        ignored_art = artwork_root / "testdata" / "logo.png"
        ignored_art.parent.mkdir()
        hidden_art = artwork_root / "misc" / "artwork.png"
        hidden_art.parent.mkdir()
        artwork_rows = [
            b"".join(
                bytes(
                    (
                        (x * 11 + y * 3) % 256,
                        (x * 5 + y * 13) % 256,
                        (x * 17 + y * 7) % 256,
                        255,
                    )
                )
                for x in range(48)
            )
            for y in range(48)
        ]
        write_rgba_png(ignored_art, 48, 48, artwork_rows)
        write_rgba_png(hidden_art, 48, 48, artwork_rows)
        assert (
            nearby_install_artwork_path(
                executable,
                current_icon,
                "Example.Tool",
                "Example Tool",
            )
            == hidden_art
        )
        # The traversal cap also bounds enumeration and closes its iterator.
        # Use real file metadata; only the enumeration stream is supplied here.
        ordinary_file = artwork_root / "ordinary.txt"
        ordinary_file.write_text("not artwork", encoding="utf-8")
        with os.scandir(artwork_root) as real_entries:
            ordinary_entry = next(entry for entry in real_entries if entry.name == ordinary_file.name)
        enumerated: list[int] = []
        closed_enumerations: list[bool] = []

        @contextlib.contextmanager
        def bounded_artwork_entries(_directory: Path) -> Any:
            def entries() -> Any:
                for index in range(1201):
                    assert index < 1200, "artwork enumeration exceeded its entry budget"
                    enumerated.append(index)
                    yield ordinary_entry

            try:
                yield entries()
            finally:
                closed_enumerations.append(True)

        with patch.object(os, "scandir", bounded_artwork_entries):
            assert nearby_install_artwork_path(
                executable, current_icon, "Example.Tool", "Example Tool"
            ) is None
        assert len(enumerated) == 1200 and closed_enumerations == [True]
        with patch.object(os, "scandir", side_effect=PermissionError("fixture")):
            assert nearby_install_artwork_path(
                executable, current_icon, "Example.Tool", "Example Tool"
            ) is None
        unrelated_root = artwork_root / "unrelated-system"
        unrelated_root.mkdir()
        unrelated_executable = unrelated_root / "ARP.exe"
        unrelated_executable.touch()
        for filename in ("BluetoothPairingSystemToastIcon.png", "NetworkLogo.png"):
            write_rgba_png(unrelated_root / filename, 48, 48, artwork_rows)
        assert (
            nearby_install_artwork_path(
                unrelated_executable,
                current_icon,
                r"ARP\Machine\X64\Steam App 3040730",
                "All You Need is Help (Free Trial)",
            )
            is None
        )
        assert "arp" in _PATH_EXECUTABLE_NOISE_WORDS
        assert (
            path_executable_icon_path(
                r"ARP\Machine\X64\Steam App 3040730",
                "All You Need is Help (Free Trial)",
            )
            is None
        )
        assert (
            path_executable_icon_path(
                r"MSIX\Microsoft.NET.Native.Framework.2.1_2.1.27427.0_x64__publisher",
                "Microsoft .NET Native Framework",
            )
            is None
        )
    assert palette_for_mode("light")["mode"] == "light"
    assert palette_for_mode("dark")["mode"] == "dark"
    assert set(MENU_THEME_ROLES.values()) <= set(LIGHT_PALETTE)
    assert set(MENU_THEME_ROLES.values()) <= set(DARK_PALETTE)
    try:
        palette_for_mode("sepia")
    except ValueError:
        pass
    else:
        raise AssertionError("unsupported palette mode was accepted")
    import tkinter as tk

    tk_root = tk.Tk()
    tk_root.withdraw()
    try:
        dpi_visits: list[int] = []
        idle_visits: list[str] = []
        dpi_probe = WindowsVisualController(
            tk_root, DpiBootstrapResult("test", "test", "test", False)
        )
        starting_scaling = float(tk_root.tk.call("tk", "scaling", "-displayof", tk_root._w))
        try:
            with patch.dict(globals(), get_window_dpi=lambda _hwnd: 144):
                with patch.object(dpi_probe, "register_toplevel"), patch.object(tk_root, "bind"):
                    tk_root.after_idle(lambda: idle_visits.append("startup"))
                    dpi_probe.initialize(dpi_visits.append)
                assert idle_visits == ["startup"] and dpi_visits == [144]
                tk_root.after_idle(lambda: idle_visits.append("later"))
                dpi_probe._sync_dpi()
                assert idle_visits == ["startup"], "DPI probe drained unrelated idle work"
                assert dpi_visits == [144], "unchanged DPI caused a reflow"
                tk_root.update_idletasks()
                assert idle_visits == ["startup", "later"]
            for new_dpi in (192, 192, 96):
                with patch.dict(globals(), get_window_dpi=lambda _hwnd: new_dpi):
                    dpi_probe._sync_dpi()
                assert dpi_probe.current_dpi == new_dpi
                assert abs(
                    float(tk_root.tk.call("tk", "scaling", "-displayof", tk_root._w))
                    - new_dpi / TK_POINTS_PER_INCH
                ) < 0.01
            assert dpi_visits == [144, 192, 96]
            # A move-only Configure may cross monitors: retain the coalesced
            # native DPI check without depending on size changes.
            with patch.object(tk_root, "after", return_value="test-after") as scheduled:
                child_event = type("DpiEvent", (), {"widget": object()})()
                dpi_probe._on_configure(child_event)
                assert not scheduled.called
                move_event = type("DpiEvent", (), {"widget": tk_root})()
                for _ in range(20):
                    dpi_probe._on_configure(move_event)
                scheduled.assert_called_once_with(100, dpi_probe._deferred_sync)
            with patch.dict(globals(), get_window_dpi=lambda _hwnd: 144):
                dpi_probe._deferred_sync()
            assert not dpi_probe._sync_pending and dpi_visits == [144, 192, 96, 144]
        finally:
            tk_root.tk.call("tk", "scaling", "-displayof", tk_root._w, starting_scaling)
        menu_theme_probe = object.__new__(WinDevPilotApp)
        menu_theme_probe.palette = palette_for_mode("light")
        menu_theme_probe._theme_widgets = []
        menu_theme_probe._theme_text_panels = []
        menu_theme_probe._theme_listboxes = []
        menu_theme_probe._theme_toplevels = []
        theme_menu = tk.Menu(tk_root, tearoff=False)
        WinDevPilotApp._register_theme_widget(
            menu_theme_probe,
            theme_menu,
            **MENU_THEME_ROLES,
        )
        assert str(theme_menu.cget("background")) == LIGHT_PALETTE["surface"]
        menu_theme_probe.palette = palette_for_mode("dark")
        WinDevPilotApp._refresh_registered_theme_widgets(menu_theme_probe)
        assert str(theme_menu.cget("background")) == DARK_PALETTE["surface"]
        assert str(theme_menu.cget("foreground")) == DARK_PALETTE["text"]
        assert str(theme_menu.cget("activebackground")) == DARK_PALETTE["button_active"]
        theme_menu.destroy()
        from tkinter import ttk

        cue_probe = object.__new__(WinDevPilotApp)
        cue_probe.root = tk_root
        cue_probe.visuals = type("CueDpiProbe", (), {"px": staticmethod(int)})()
        cue_probe.busy = True
        cue_probe._busy_kind = "update"
        cue_probe._client_animations_enabled = True
        cue_probe._progress_after_id = None
        cue_probe.progress_var = tk.DoubleVar(tk_root, value=0.0)
        cue_probe.progress = ttk.Progressbar(tk_root, variable=cue_probe.progress_var)
        cue_probe._progress_activity = tk.Canvas(cue_probe.progress)
        cue_probe._progress_activity_base = cue_probe._progress_activity.create_rectangle(0, 0, 1, 1)
        cue_probe._progress_activity_pulse = cue_probe._progress_activity.create_rectangle(0, 0, 1, 1)
        cue_items = cue_probe._progress_activity.find_all()
        cue_timers = set(tk_root.tk.call("after", "info"))
        for mode in ("light", "dark"):
            cue_probe.palette = palette_for_mode(mode)
            with patch.object(cue_probe.progress, "winfo_width", return_value=300), patch.object(
                cue_probe.progress, "winfo_height", return_value=18
            ):
                for instant in (0.0, 0.35, 0.7, 1.39):
                    with patch.object(time, "monotonic", return_value=instant):
                        cue_probe._draw_update_progress_activity()
                    assert cue_probe._progress_activity.winfo_manager() == "place"
                    assert cue_probe._progress_activity.find_all() == cue_items
                    assert cue_probe.progress_var.get() == 0.0, "activity invented completion"
                    assert cue_probe._progress_activity.itemcget(
                        cue_probe._progress_activity_base, "fill"
                    ) == cue_probe.palette["progress"]
                cue_probe._client_animations_enabled = False
                cue_probe._draw_update_progress_activity()
                still_coords = cue_probe._progress_activity.coords(cue_probe._progress_activity_pulse)
                with patch.object(time, "monotonic", return_value=50.0):
                    cue_probe._draw_update_progress_activity()
                assert cue_probe._progress_activity.coords(cue_probe._progress_activity_pulse) == still_coords
                cue_probe._client_animations_enabled = True
        assert set(tk_root.tk.call("after", "info")) == cue_timers, "cue added an animation timer"
        cue_probe._set_progress_value(33.3, animate=False)
        assert not cue_probe._progress_activity.winfo_manager()
        cue_probe._set_progress_value(0, animate=False)
        assert cue_probe._progress_activity.winfo_manager() == "place"
        cue_probe._busy_kind = "scan"
        cue_probe._draw_update_progress_activity()
        assert not cue_probe._progress_activity.winfo_manager()
        cue_probe._busy_kind = "update"
        cue_probe.busy = False
        cue_probe._draw_update_progress_activity()
        assert not cue_probe._progress_activity.winfo_manager()
        # Replay the reported held-selection path with real Tk progress widgets,
        # but no provider process, installer, UAC, or real settings writes.
        cue_probe._last_scan_all_packages = False
        cue_probe._scan_active = False
        cue_probe._update_request_cue_until = 0.0
        cue_probe._update_request_cue_after_id = None
        cue_probe.cancel_requested = threading.Event()
        cue_probe.summary_var = tk.StringVar(tk_root)
        cue_probe._hide_notification_banner = Mock()
        cue_probe._show_notification_banner = Mock()
        cue_probe._append_log = Mock()
        cue_probe.logger = Mock()
        cue_probe.update_button = Mock()
        cue_probe._confirm_update_batch = Mock()
        cue_probe.messagebox = Mock()
        cue_probe.events = queue.Queue()
        cue_probe._item_icon_source_cache = {}
        cue_probe._refresh_item_row = Mock()
        cue_probe._refresh_scan_summary_counts = Mock()
        held_request_item = UpdateItem(
            provider="winget", package_id="Example.Held", name="Held example", current="1",
            available="2", scope="user", selected=True,
            classification=CLASS_MANUAL_REVIEW, applicability_prediction=PREDICTION_UNKNOWN,
            prediction_source="attempt-hold", status="Held after failed attempt",
        )
        held_request_record = {
            "strategy_revision": WINGET_ATTEMPT_STRATEGY_REVISION,
            "item": {"provider": "winget"}, "outcome": "failed",
        }
        cue_probe.settings = Mock(data={"attempt_holds": {held_request_item.candidate_key: held_request_record}})
        request_provider = WingetProvider()
        request_provider.preflight_item = Mock(side_effect=AssertionError("held request queried provider"))
        cue_probe.providers = {"winget": request_provider}
        cue_probe._provider_operation_locks = {"winget": threading.RLock()}
        cue_probe.items = {held_request_item.key: held_request_item}
        cue_probe._scan_view_items = {False: cue_probe.items, True: {}}
        cue_probe._start_guarded_worker = lambda target, **_kwargs: target()
        def request_busy(value: bool, _activity: str = "", *, kind: str = "") -> None:
            cue_probe.busy = value
            cue_probe._busy_kind = kind if value else ""
            cue_probe._draw_update_progress_activity()
        cue_probe._set_busy = request_busy
        cue_probe._refresh_update_button_readiness()
        assert cue_probe.update_button.configure.call_args.kwargs["text"] == "Review selected"
        assert cue_probe.update_button.configure.call_args.kwargs["state"] == "normal"
        cue_probe._set_progress_value(100, animate=False)
        cue_probe.cancel_requested.set()  # A prior stop must not cancel the next request.
        with patch.object(time, "monotonic", return_value=10.0):
            cue_probe.update_selected()
            assert not cue_probe.busy and not cue_probe.cancel_requested.is_set()
            assert cue_probe.progress_var.get() == 0.0
            assert cue_probe._progress_activity.winfo_manager() == "place"
        request_provider.preflight_item.assert_not_called()
        cue_probe._confirm_update_batch.assert_not_called()
        assert "No update started" in cue_probe.summary_var.get()
        assert "Held after failed attempt" in cue_probe.summary_var.get()
        assert cue_probe._show_notification_banner.call_args.kwargs["level"] == "warning"
        assert "Test once" in cue_probe._show_notification_banner.call_args.args[0]
        cue_probe.logger.event.assert_called_with(
            "update_request_not_started", reason="selected-packages-need-review", item_count=1,
            candidate_keys=[held_request_item.candidate_key],
        )
        with patch.object(time, "monotonic", return_value=10.2):
            cue_probe._draw_update_progress_activity()
            assert cue_probe._progress_activity.winfo_manager() == "place"
            cue_probe._scan_active = True
            cue_probe._draw_update_progress_activity()
            assert not cue_probe._progress_activity.winfo_manager(), "request cue covered a scan"
            cue_probe._scan_active = False
        cue_probe._cancel_after_id("_update_request_cue_after_id")
        cue_probe._finish_update_request_cue()
        assert not cue_probe._progress_activity.winfo_manager()
        assert cue_probe.settings.data["attempt_holds"][held_request_item.candidate_key] == held_request_record
        # Fresh metadata does not accidentally release the independent hold.
        held_request_item.prediction_source = "winget-show"
        assert not cue_probe._selected_winget_rows_needing_preflight([held_request_item])
        # Mixed selections still confirm only ordinary updates through Normal Update.
        ordinary_request_item = dataclasses.replace(
            held_request_item, package_id="Example.Ordinary", status="Ready",
            classification=CLASS_SIMPLE_UPGRADE, applicability_prediction=PREDICTION_ORDINARY,
        )
        cue_probe.items[ordinary_request_item.key] = ordinary_request_item
        cue_probe.messagebox.askokcancel.return_value = True
        cue_probe.update_selected()
        cue_probe._confirm_update_batch.assert_called_once_with([ordinary_request_item], probe_once=False)
        assert not cue_probe.busy, "confirmation waited for the decorative cue"
        cue_probe._cancel_after_id("_update_request_cue_after_id")
        cue_probe._finish_update_request_cue()
        # The preliminary worker gets the same activity cue; cancelling it cannot
        # continue into an installer, and a later request starts with a clear stop flag.
        cue_probe.items = {ordinary_request_item.key: ordinary_request_item}
        cue_probe._scan_view_items[False] = cue_probe.items
        ordinary_request_item.applicability_prediction = PREDICTION_PENDING
        request_provider.preflight_item = Mock(return_value=dataclasses.replace(
            ordinary_request_item, applicability_prediction=PREDICTION_ORDINARY
        ))
        cue_probe._confirm_update_batch.reset_mock()
        cue_probe.update_selected()
        assert cue_probe._busy_kind == "selected-preflight"
        assert cue_probe._progress_activity.winfo_manager() == "place"
        event_name, event_payload = cue_probe.events.get_nowait()
        assert event_name == "selected_preflight_done"
        cue_probe.cancel_requested.set()
        cue_probe._finish_selected_winget_preflight(*event_payload)
        cue_probe._confirm_update_batch.assert_not_called()
        assert cue_probe.summary_var.get() == "No update started — cancelled during the checks"
        cue_probe._cancel_after_id("_update_request_cue_after_id")
        cue_probe._finish_update_request_cue()
        cue_probe.update_button = Mock()
        cue_probe.items.clear()
        cue_probe._refresh_update_button_readiness()
        assert cue_probe.update_button.configure.call_args.kwargs["state"] == "disabled"
        cue_probe.progress.destroy()
        batch_progress_probe = object.__new__(WinDevPilotApp)
        batch_progress_probe._busy_kind = "update"
        progress_item = UpdateItem(provider="winget", package_id="Example.App", name="Example", current="1", available="2")
        batch_progress_probe._active_operation_items = {progress_item.key: progress_item, "second": None}
        batch_progress_probe._update_progress_completed_keys = set()
        batch_progress_probe._set_scan_view_item_status = Mock(return_value=progress_item)
        batch_progress_probe._set_progress_value = Mock()
        batch_progress_probe._show_command_result = Mock()
        batch_progress_probe.logger = Mock()
        for index in (1, 2):
            batch_progress_probe._dispatch_event(
                "item_status", (progress_item.key, "Queued for administrator", index, 2)
            )
        batch_progress_probe._set_progress_value.assert_not_called()
        for _ in range(2):
            batch_progress_probe._dispatch_event("command_result", (progress_item, {"success": False}))
            batch_progress_probe._set_progress_value.assert_called_with(50.0)
        assert batch_progress_probe._update_progress_completed_keys == {progress_item.key}
        gradient_probe = object.__new__(WinDevPilotApp)
        gradient_probe.visuals = type("GradientDpiProbe", (), {"px": staticmethod(int)})()
        gradient_probe.busy = False
        gradient_probe._client_animations_enabled = True
        gradient_probe._busy_pulse_offset = 60
        gradient_canvases = (
            ("header_canvas", "header_gradient", 128, 1, "_draw_header_gradient"),
            ("main_splitter", "splitter_gradient", 96, 3, "_draw_main_splitter_gradient"),
            ("accent_canvas", "accent_gradient", 96, 0, "_draw_accent_gradient"),
        )
        for attribute, _tag, _bands, _overlays, _draw in gradient_canvases:
            setattr(gradient_probe, attribute, tk.Canvas(tk_root))
        header_text = gradient_probe.header_canvas.create_text(8, 8, text="Keep header")
        gradient_probe.header_search_window_id = gradient_probe.header_canvas.create_window(
            0, 0, window=tk.Frame(gradient_probe.header_canvas), anchor="ne"
        )
        previous_gradient_state: dict[str, tuple[Any, ...]] = {}
        for mode, width, height, busy in (
            ("light", 1200, 78, False), ("light", 1500, 78, False),
            ("light", 1300, 117, False), ("dark", 1300, 117, False),
            ("dark", 1800, 156, False), ("dark", 1800, 156, True),
            ("dark", 1800, 156, False), ("light", 1, 1, False),
            ("light", 95, 5, False), ("light", 129, 12, False),
            ("light", 1200, 78, False),
        ):
            gradient_probe.palette = palette_for_mode(mode)
            gradient_probe.busy = busy
            for attribute, tag, maximum_bands, overlay_count, draw in gradient_canvases:
                canvas = getattr(gradient_probe, attribute)
                canvas.place(x=0, y=0, width=width, height=height)
                tk_root.update_idletasks()
                assert (canvas.winfo_width(), canvas.winfo_height()) == (width, height)
                getattr(gradient_probe, draw)()
                raster = canvas._wdp_gradient_raster
                signature = raster["strip_key"]
                ids = (raster["item"], str(raster["strip"]), str(raster["image"]))
                prior = previous_gradient_state.get(tag)
                if prior is not None:
                    assert prior[1] == ids, "resize recreated gradient images or canvas item"
                previous_gradient_state[tag] = (signature, ids)
                band_count = min(width, maximum_bands)
                assert (raster["image"].width(), raster["image"].height()) == (width, height)
                assert len(canvas.find_withtag(tag)) == 1 + overlay_count
                assert len(canvas.find_withtag(tag + "_overlay")) == overlay_count
                assert canvas.coords(raster["item"]) == [0, 0]
                assert canvas.type(raster["item"]) == "image"
                for index in range(band_count):
                    left = index * width // band_count
                    right = (index + 1) * width // band_count
                    color = gradient_probe._hex_to_rgb(
                        gradient_probe._gradient_stop_color(signature[2], (index + 0.5) / band_count)
                    )
                    for x in (left, right - 1):
                        assert raster["image"].get(x, 0) == color
                        assert raster["image"].get(x, height - 1) == color
                stable_items = canvas.find_all()
                getattr(gradient_probe, draw)()
                assert stable_items == canvas.find_all(), "unchanged draw allocated canvas items"
            header = gradient_probe.header_canvas
            assert header.find_all().index(header_text) > max(
                header.find_all().index(item_id) for item_id in header.find_withtag("header_gradient")
            )
            assert header.coords(gradient_probe.header_search_window_id) == [width - 14, 13]
            pulse = gradient_probe.accent_canvas
            assert len(pulse.find_all()) == 6
            assert all(
                pulse.itemcget(item_id, "state") == ("normal" if busy else "hidden")
                for item_id in gradient_probe._accent_pulse_ids
            )
        for attribute, _tag, _bands, _overlays, _draw in gradient_canvases:
            getattr(gradient_probe, attribute).destroy()

        animation_probe = object.__new__(WinDevPilotApp)
        animation_probe.busy = True
        animation_probe._resize_hold = type("ResizeLoopProbe", (), {"_in_loop": True})()
        animation_probe._activity_after_id = None
        animation_probe.root = Mock()
        animation_probe.activity_var = Mock()
        WinDevPilotApp._animate_activity(animation_probe)
        animation_probe.activity_var.set.assert_not_called()
        animation_probe.root.after.assert_called_once_with(
            WINDOW_DRAG_BUSY_ANIMATION_POLL_MS,
            animation_probe._animate_activity,
        )
        progress_probe = object.__new__(WinDevPilotApp)
        progress_probe._closing = False
        progress_probe._resize_hold = type(
            "ProgressResizeProbe", (), {"_in_loop": True}
        )()
        progress_probe._active_scan_generation = 7
        progress_probe._scan_active = True
        progress_probe._scan_progress_determinate = False
        progress_probe.progress = Mock()
        progress_probe._set_progress_value = Mock()
        progress_probe._refresh_scan_summary_counts = Mock()
        WinDevPilotApp._show_scan_progress(progress_probe, 7, 1, 3, "WinGet", False)
        assert "1/3" in progress_probe._activity_base
        progress_probe.progress.configure.assert_not_called()
        progress_probe._set_progress_value.assert_not_called()
        progress_probe._refresh_scan_summary_counts.assert_not_called()
        progress_probe._resize_hold._in_loop = False
        WinDevPilotApp._show_scan_progress(progress_probe, 7, 2, 3, "npm", False)
        progress_probe.progress.stop.assert_called_once_with()
        progress_probe.progress.configure.assert_called_once_with(mode="determinate")
        progress_probe._set_progress_value.assert_called_once_with(200 / 3)
        progress_probe._refresh_scan_summary_counts.assert_called_once_with()
        rebuild_probe = object.__new__(WinDevPilotApp)
        rebuild_probe._resize_hold = type(
            "RebuildResizeProbe", (), {"_in_loop": True}
        )()
        rebuild_probe._rebuild_after_id = "pending"
        rebuild_probe._rebuild_prime_cached_first_paint = True
        rebuild_probe._rebuild_tree = Mock()
        rebuild_probe.root = Mock()
        WinDevPilotApp._run_scheduled_rebuild_tree(rebuild_probe)
        rebuild_probe._rebuild_tree.assert_not_called()
        rebuild_probe.root.after.assert_called_once_with(
            WINDOW_DRAG_BUSY_ANIMATION_POLL_MS,
            rebuild_probe._run_scheduled_rebuild_tree,
        )
        catalog_decode_probe = object.__new__(WinDevPilotApp)
        catalog_decode_probe._closing = False
        catalog_decode_probe._resize_hold = type(
            "CatalogResizeProbe", (), {"_in_loop": True}
        )()
        catalog_decode_probe._icon_catalog_decode_after_id = "pending"
        catalog_decode_probe._icon_catalog_decode_queue = deque(
            [("package", 24, "cached.png")]
        )
        catalog_decode_probe.root = Mock()
        WinDevPilotApp._decode_catalog_icons(catalog_decode_probe)
        assert list(catalog_decode_probe._icon_catalog_decode_queue) == [
            ("package", 24, "cached.png")
        ]
        catalog_decode_probe.root.after.assert_called_once_with(
            WINDOW_DRAG_BUSY_ANIMATION_POLL_MS,
            catalog_decode_probe._decode_catalog_icons,
        )
        catalog_result_probe = object.__new__(WinDevPilotApp)
        catalog_result_probe._closing = False
        catalog_result_probe._resize_hold = type(
            "CatalogResultResizeProbe", (), {"_in_loop": True}
        )()
        catalog_result_probe._icon_catalog_load_generation = 4
        catalog_result_probe.root = Mock()
        catalog_entries = {"package": {}}
        catalog_blobs = {"cached.png": b"fixture"}
        WinDevPilotApp._finish_icon_catalog_load(
            catalog_result_probe,
            4,
            catalog_entries,
            catalog_blobs,
            "",
            0.01,
        )
        assert not hasattr(catalog_result_probe, "_icon_catalog_loaded")
        catalog_result_probe.root.after.assert_called_once_with(
            WINDOW_DRAG_BUSY_ANIMATION_POLL_MS,
            catalog_result_probe._finish_icon_catalog_load,
            4,
            catalog_entries,
            catalog_blobs,
            "",
            0.01,
        )
        icon_priority_probe = object.__new__(WinDevPilotApp)
        icon_priority_probe._closing = False
        icon_priority_probe._resize_hold = type(
            "PriorityResizeProbe", (), {"_in_loop": True}
        )()
        icon_priority_probe._icon_memory_priority_after_id = "pending"
        icon_priority_probe.root = Mock()
        icon_priority_probe.tree = Mock()
        WinDevPilotApp._prioritize_visible_ready_icon_memory_load(icon_priority_probe)
        icon_priority_probe.tree.get_children.assert_not_called()
        icon_priority_probe.root.after.assert_called_once_with(
            WINDOW_DRAG_BUSY_ANIMATION_POLL_MS,
            icon_priority_probe._prioritize_visible_ready_icon_memory_load,
        )
        icon_load_probe = object.__new__(WinDevPilotApp)
        icon_load_probe._closing = False
        icon_load_probe._resize_hold = type(
            "IconLoadResizeProbe", (), {"_in_loop": True}
        )()
        icon_load_probe._icon_memory_load_after_id = "pending"
        icon_load_probe._icon_memory_load_queue = deque(
            [("package", 24, "light")]
        )
        icon_load_probe.root = Mock()
        icon_load_probe.tree = Mock()
        WinDevPilotApp._load_ready_icons_into_memory(icon_load_probe)
        assert list(icon_load_probe._icon_memory_load_queue) == [
            ("package", 24, "light")
        ]
        icon_load_probe.tree.exists.assert_not_called()
        icon_load_probe.root.after.assert_called_once_with(
            WINDOW_DRAG_BUSY_ANIMATION_POLL_MS,
            icon_load_probe._load_ready_icons_into_memory,
        )

        # Native move/resize may postpone decorative painting, never semantic
        # completion. Keep this regression guard beside the gesture policies.
        completion_probe = object.__new__(WinDevPilotApp)
        completion_probe._closing = False
        completion_probe._resize_hold = type(
            "CompletionResizeProbe", (), {"_in_loop": True}
        )()
        completion_probe._poll_after_id = "pending"
        completion_probe.events = queue.Queue()
        completion_probe.events.put(("log", "first batched line"))
        completion_probe.events.put(("log", "second batched line"))
        completion_probe.events.put(("scan_done", ("completed",)))
        completion_probe._finish_scan = Mock()
        completion_probe._paint_log_messages = Mock()
        completion_probe.logger = Mock()
        completion_probe.logger.consume_writer_error.return_value = ""
        completion_probe.logger.queue_depth_metrics.return_value = {}
        completion_probe.root = Mock()
        completion_probe.busy = True
        completion_probe._scan_active = True
        WinDevPilotApp._poll_events(completion_probe)
        completion_probe._finish_scan.assert_called_once_with("completed")
        completion_probe._paint_log_messages.assert_called_once_with(
            ["first batched line", "second batched line"]
        )
        assert completion_probe.logger.write.call_count == 2
        completion_probe.root.after.assert_called_once_with(
            UI_EVENT_BUSY_DELAY_MS, completion_probe._poll_events
        )

        # Keep Tk geometry managers and the native callback lifetime real. Only
        # mapped/normal state is substituted so this remains a withdrawn test.
        resize_root = tk.Toplevel(tk_root)
        resize_root.withdraw()
        resize_root.winfo_ismapped = lambda: True
        resize_root.state = lambda: "normal"
        resize_children = (tk.Frame(resize_root), tk.Frame(resize_root))
        resize_children[0].pack(side="top", fill="x", padx=3, pady=(1, 2))
        resize_children[1].pack(side="top", fill="both", expand=True, padx=7)
        packed_options = [child.pack_info() for child in resize_children]
        resize_errors: list[str] = []
        resize_hold = WindowsResizeHold(resize_root, resize_children, resize_errors.append)

        class NoTkAtNativeBoundary:
            def __getattr__(self, name: str) -> Any:
                raise AssertionError(f"native resize handler touched Tk: {name}")

        resize_hold.root = NoTkAtNativeBoundary()
        for message, wparam in ((0x0231, 0), (0x0214, 0), (0x0216, 0), (0x0005, 0),
                                (0x0215, 0), (0x001F, 0), (0x02E0, 0), (0x0232, 0),
                                (0x0005, 1), (0x0005, 2)):
            resize_hold._on_message(message, wparam)
        resize_hold.root = resize_root
        if os.name == "nt":
            assert resize_hold.install()
            assert resize_hold.install(), "attaching twice must be harmless"
            assert WindowsResizeHold._native_instances[id(resize_hold)] is resize_hold
            subclass_library, subclass_procedure = _resize_subclass_api()
            assert subclass_library.DefSubclassProc.restype is ctypes.c_ssize_t
            assert subclass_library.SetWindowSubclass.argtypes[2] is ctypes.c_size_t
            assert subclass_procedure._argtypes_ == (
                ctypes.c_void_p, ctypes.c_uint, ctypes.c_size_t, ctypes.c_ssize_t,
                ctypes.c_size_t, ctypes.c_size_t,
            )
        resize_hold._on_message(0x0214)  # No modal loop: do not hold.
        assert not resize_hold._layout
        normal_switch_interval = sys.getswitchinterval()
        resize_hold._on_message(0x0231)
        assert sys.getswitchinterval() <= min(
            normal_switch_interval,
            WINDOW_DRAG_THREAD_SWITCH_INTERVAL_SECONDS,
        )
        resize_hold._on_message(0x0216)  # WM_MOVING
        assert not resize_hold._layout
        move_event = type("ResizeEvent", (), {"widget": resize_root})()
        with patch.object(resize_hold, "_service") as service:
            resize_hold._on_configure(move_event)
            service.assert_not_called()
            resize_hold._on_message(0x0214)  # First WM_SIZING arms the hold.
            resize_hold._on_configure(move_event)
            service.assert_called_once()
        resize_hold._on_message(0x0215)
        assert not resize_hold._in_loop
        assert math.isclose(sys.getswitchinterval(), normal_switch_interval)
        resize_hold._on_message(0x0232)
        pending_idle: list[bool] = []
        resize_root.after_idle(lambda: pending_idle.append(True))
        for message, wparam in ((0x0232, 0), (0x0215, 0), (0x001F, 0),
                                (0x02E0, 0), (0x0005, 1), (0x0005, 2)):
            resize_hold._on_message(0x0231)
            resize_hold._on_message(0x0214)
            assert not resize_hold._layout, "native callback entered Tk"
            resize_hold._service()
            assert len(resize_hold._layout) == 2
            held_options = [child.place_info() for child in resize_children]
            resize_hold._on_message(0x0214)
            assert held_options == [child.place_info() for child in resize_children]
            resize_hold._on_message(message, wparam)
            resize_hold._on_message(message, wparam)
            resize_hold._service()
            assert not resize_hold._layout
            assert resize_hold._after_id is None, "resize release kept polling while idle"
            assert tuple(resize_root.pack_slaves()) == resize_children
            assert packed_options == [child.pack_info() for child in resize_children]
            resize_hold._on_message(0x0214)
            assert not resize_hold._layout, "cancelled/DPI-changed gesture reengaged hold"
        assert not pending_idle, "native resize handling dispatched unrelated idle work"
        resize_root.update_idletasks()
        assert pending_idle == [True]
        resize_hold._on_message(0x0231)
        resize_hold._on_message(0x0214)
        resize_hold._service()
        resize_hold.suspend()  # Theme/DPI metric updates also use this path.
        assert packed_options == [child.pack_info() for child in resize_children]
        resize_hold._on_message(0x0231)
        resize_hold._on_message(0x0214)
        resize_hold._service()
        assert resize_hold._after_id is not None
        resize_hold._on_message(0x0232)
        resize_root.after_cancel(resize_hold._after_id)  # Simulate this timer being dispatched.
        resize_hold._poll_release()
        assert not resize_hold._layout and resize_hold._after_id is None

        original_place = resize_children[1].place

        def failed_resize_place(**_kwargs: Any) -> None:
            raise RuntimeError("fixture: placement failed")

        resize_children[1].place = failed_resize_place
        resize_hold._on_message(0x0231)
        resize_hold._on_message(0x0214)
        resize_hold._service()
        resize_children[1].place = original_place
        assert not resize_hold._layout
        assert packed_options == [child.pack_info() for child in resize_children]
        assert len(resize_errors) == 1 and resize_hold._disabled
        resize_hold.close()
        resize_hold.close()
        assert id(resize_hold) not in WindowsResizeHold._native_instances
        if os.name == "nt":
            destroy_hold = WindowsResizeHold(resize_root, resize_children)
            assert destroy_hold.install()
            destroy_hold._on_message(0x0231)
            destroy_hold._on_message(0x0214)
            destroy_hold._service()
            assert destroy_hold._layout and destroy_hold._after_id is not None
            resize_root.destroy()  # Exercise window-destruction cleanup without explicit close().
            assert id(destroy_hold) not in WindowsResizeHold._native_instances
            assert destroy_hold._closed and not destroy_hold._hwnd
            assert math.isclose(sys.getswitchinterval(), normal_switch_interval)
        else:
            resize_root.destroy()

        # Real Tcl timers, with the clock and pointer position supplied at their
        # boundaries. Scrolling must not create a timer for every notification.
        from tkinter import ttk

        scroll_probe = WinDevPilotApp.__new__(WinDevPilotApp)
        scroll_probe.tk = tk
        scroll_probe.root = tk_root
        scroll_probe.tree = ttk.Treeview(tk_root)
        scroll_probe._closing = False
        scroll_probe._hover_row = ""
        scroll_probe._tree_hover_needs_refresh = False
        scroll_probe._icon_memory_load_queue = deque()
        scroll_probe._package_icon_ready = set()
        scroll_probe._icon_memory_priority_after_id = None
        scroll_probe._icon_hydration_after_id = None
        scroll_probe._icon_scroll_quiet_until = 0.0
        scroll_probe._tree_wheel_rows_per_notch = 3
        scroll_probe._tree_wheel_remainder = 0
        wheel_event = tk.Event()
        wheel_event.state = 0
        with patch.object(scroll_probe.tree, "yview_scroll") as wheel_scroll:
            wheel_event.delta = 120
            assert scroll_probe._tree_mousewheel(wheel_event) is None
            wheel_scroll.assert_not_called()  # Continue to the untouched class binding.
            wheel_event.delta = 15
            for _ in range(8):
                assert scroll_probe._tree_mousewheel(wheel_event) == "break"
            assert [call.args for call in wheel_scroll.call_args_list] == [(-1, "units")] * 3
            assert scroll_probe._tree_wheel_remainder == 0
            for modifier in (1, 4, 8, 0x20000):
                scroll_probe._tree_wheel_remainder = 45
                wheel_event.state = modifier
                assert scroll_probe._tree_mousewheel(wheel_event) is None
                assert scroll_probe._tree_wheel_remainder == 0
        scroll_bar = ttk.Scrollbar(tk_root)
        prior_timers = set(tk_root.tk.call("after", "info"))
        with patch.object(time, "monotonic", return_value=100.0):
            for index in range(500):
                scroll_probe._tree_yscroll(scroll_bar, index / 1000, (index + 20) / 1000)
        assert scroll_probe._icon_memory_priority_after_id is None
        assert len(set(tk_root.tk.call("after", "info")) - prior_timers) == 1
        assert scroll_bar.get() == (0.499, 0.519)
        hydration_timer = scroll_probe._icon_hydration_after_id
        with patch.object(time, "monotonic", return_value=100.2):
            scroll_probe._tree_yscroll(scroll_bar, 0.5, 0.52)
        assert scroll_probe._icon_hydration_after_id == hydration_timer
        assert scroll_probe._icon_scroll_quiet_until == 100.52
        scroll_probe._icon_memory_load_queue.append(("fixture", 32, "light"))
        with patch.object(time, "monotonic", return_value=100.2):
            scroll_probe._tree_yscroll(scroll_bar, 0.51, 0.53)
            priority_timer = scroll_probe._icon_memory_priority_after_id
            scroll_probe._tree_yscroll(scroll_bar, 0.52, 0.54)
        assert priority_timer is not None
        assert scroll_probe._icon_memory_priority_after_id == priority_timer
        scroll_probe._cancel_after_id("_icon_memory_priority_after_id")
        scroll_probe._icon_memory_load_queue.clear()
        # A callback already due during a continued gesture must reschedule,
        # not identify rows, decode files, or force pending Tk work to run.
        scroll_probe._cancel_after_id("_icon_hydration_after_id")
        with patch.object(time, "monotonic", return_value=100.3), patch.object(
            scroll_probe.tree, "get_children", side_effect=AssertionError("early hydration")
        ), patch.object(
            scroll_probe.tree, "identify_region", side_effect=AssertionError("scroll hit test")
        ):
            scroll_probe._hydrate_visible_icons()
            scroll_probe._tree_motion(tk.Event())
        assert scroll_probe._icon_hydration_after_id is not None
        assert scroll_probe._tree_hover_needs_refresh
        scroll_probe._cancel_after_id("_icon_hydration_after_id")
        # Re-hit-test at the current pointer position exactly once on settling,
        # including when the pointer has not moved since the gesture began.
        with patch.object(time, "monotonic", return_value=100.6), patch.object(
            scroll_probe.tree, "winfo_pointerxy", return_value=(140, 260)
        ), patch.object(
            scroll_probe.tree, "winfo_containing", return_value=scroll_probe.tree
        ), patch.object(scroll_probe.tree, "winfo_rootx", return_value=40), patch.object(
            scroll_probe.tree, "winfo_rooty", return_value=60
        ), patch.object(scroll_probe, "_tree_motion") as settled_motion:
            scroll_probe._hydrate_visible_icons()  # Empty tree still restores hover.
            scroll_probe._refresh_tree_hover_after_scroll()
            assert settled_motion.call_count == 1
            restored_event = settled_motion.call_args.args[0]
            assert (restored_event.x, restored_event.y) == (100, 200)
            assert (restored_event.x_root, restored_event.y_root) == (140, 260)
        scroll_probe._tree_hover_needs_refresh = True
        with patch.object(scroll_probe.tree, "winfo_containing", return_value=None), patch.object(
            scroll_probe, "_tree_motion", side_effect=AssertionError("pointer outside list")
        ):
            scroll_probe._refresh_tree_hover_after_scroll()
        assert not scroll_probe._tree_hover_needs_refresh
        scroll_probe._hover_row = "fixture"
        with patch.object(scroll_probe, "_tree_leave") as clear_hover:
            scroll_probe._tree_yscroll(scroll_bar, 0.6, 0.7)
            clear_hover.assert_called_once()
        scroll_probe._cancel_after_id("_icon_hydration_after_id")
        scroll_probe._closing = True
        with patch.object(scroll_probe, "_refresh_tree_hover_after_scroll") as closed_hover:
            scroll_probe._hydrate_visible_icons()
            closed_hover.assert_not_called()
        scroll_probe.tree.destroy()
        scroll_bar.destroy()
        assert set(tk_root.tk.call("after", "info")) == prior_timers
        flat_icon = tk.PhotoImage(width=16, height=16)
        saturated_flat_icon = tk.PhotoImage(width=16, height=16)
        gray_flat_icon = tk.PhotoImage(width=16, height=16)
        detailed_icon = tk.PhotoImage(width=16, height=16)
        for y in range(16):
            for x in range(16):
                flat_icon.put("#ffffff", (x, y))
                saturated_flat_icon.put("#0088ff", (x, y))
                gray_flat_icon.put("#888888", (x, y))
                detailed_icon.put("#000000" if (x + y) % 2 else "#00aaff", (x, y))
        assert not tk_image_has_visual_detail(flat_icon)
        assert tk_image_has_visual_detail(saturated_flat_icon)
        assert not tk_image_has_visual_detail(gray_flat_icon)
        assert tk_image_has_visual_detail(detailed_icon)
    finally:
        tk_root.destroy()
    flat_rows = [bytes((255, 255, 255, 255)) * 16 for _ in range(16)]
    saturated_rows = [bytes((0, 136, 255, 255)) * 16 for _ in range(16)]
    gray_rows = [bytes((136, 136, 136, 255)) * 16 for _ in range(16)]
    detailed_rows = [
        b"".join(
            bytes((0, 0, 0, 255)) if (x + y) % 2 else bytes((0, 170, 255, 255)) for x in range(16)
        )
        for y in range(16)
    ]
    transparent_noise_rows = [
        b"".join(
            bytes(((x * 41) % 256, (y * 67) % 256, ((x + y) * 29) % 256, 0))
            for x in range(16)
        )
        for y in range(16)
    ]
    monochrome_silhouette_rows = [
        b"".join(
            bytes((255, 255, 255, 255))
            if 3 <= x <= 12 and 3 <= y <= 12
            else bytes((0, 0, 0, 0))
            for x in range(16)
        )
        for y in range(16)
    ]
    assert not rgba_rows_have_visual_detail(flat_rows, 16, 16)
    assert rgba_rows_have_visual_detail(saturated_rows, 16, 16)
    assert not rgba_rows_have_visual_detail(gray_rows, 16, 16)
    assert rgba_rows_have_visual_detail(detailed_rows, 16, 16)
    assert not rgba_rows_have_visual_detail(transparent_noise_rows, 16, 16)
    assert rgba_rows_have_visual_detail(monochrome_silhouette_rows, 16, 16)
    duplicate_base_rows = [bytes((60, 120, 180, 255)) * 16 for _ in range(16)]
    duplicate_rounded_rows = [bytearray(row) for row in duplicate_base_rows]
    for pixel_index in range(0, 16 * 16, 12):
        row_index, column_index = divmod(pixel_index, 16)
        duplicate_rounded_rows[row_index][column_index * 4] += 1
    assert rgba_rows_are_conservative_near_duplicate(
        duplicate_base_rows,
        [bytes(row) for row in duplicate_rounded_rows],
        16,
        16,
    )
    different_alpha_rows = list(duplicate_base_rows)
    different_alpha_row = bytearray(different_alpha_rows[0])
    different_alpha_row[3] = 254
    different_alpha_rows[0] = bytes(different_alpha_row)
    assert not rgba_rows_are_conservative_near_duplicate(
        duplicate_base_rows,
        different_alpha_rows,
        16,
        16,
    )
    assert not rgba_rows_are_conservative_near_duplicate(
        duplicate_base_rows,
        [bytes((68, 120, 180, 255)) * 16 for _ in range(16)],
        16,
        16,
    )
    gallery_base_rows = [
        b"".join(
            bytes((x * 12, y * 12, (x + y) * 6, 255))
            for x in range(16)
        )
        for y in range(16)
    ]
    gallery_scaled_rows = _scale_rgba_bilinear(gallery_base_rows, 16, 16, 64, 64)
    gallery_base_signature = icon_gallery_visual_signature(gallery_base_rows, 16, 16)
    gallery_scaled_signature = icon_gallery_visual_signature(gallery_scaled_rows, 64, 64)
    assert gallery_base_signature is not None and gallery_scaled_signature is not None
    assert icon_gallery_signatures_match(gallery_base_signature, gallery_scaled_signature)
    gallery_other_rows = [bytes((30, 180, 220, 255)) * 16 for _ in range(16)]
    gallery_other_signature = icon_gallery_visual_signature(gallery_other_rows, 16, 16)
    assert gallery_other_signature is not None
    assert not icon_gallery_signatures_match(gallery_base_signature, gallery_other_signature)
    assert normalized_identity_fuzzy_match("windowsterminal", "microsoftwindowsterminal")
    assert normalized_identity_fuzzy_match("appinstaller", "microsoftdesktopappinstaller")
    assert not normalized_identity_fuzzy_match("filelock", "microsoftpowertoysfilelocksmith")
    translucent_canvas = [bytearray((255, 255, 255, 30) * 16) for _ in range(16)]
    for y in range(6, 10):
        for x in range(6, 10):
            translucent_canvas[y][x * 4 : x * 4 + 4] = bytes((220, 30, 55, 255))
    assert _display_artwork_rgba_bbox(
        [bytes(row) for row in translucent_canvas], 16, 16
    ) == (4, 4, 11, 11)
    filtered_row = bytearray((250, 1, 127, 128, 255, 0, 64, 192))
    previous_row = bytearray((10, 255, 129, 128, 1, 0, 192, 64))
    expected_up_row = bytes(
        (current + previous) & 0xFF
        for current, previous in zip(filtered_row, previous_row, strict=True)
    )
    _png_up_filter_in_place(filtered_row, previous_row)
    assert bytes(filtered_row) == expected_up_row
    for width in (0, 1, 7, 8, 9, 31, 257, 4096):
        for phase in range(3):
            filtered_row = bytearray((0x80, 0xFF, 0x01)[i % 3] for i in range(width))
            previous_row = bytearray((0x80, 0xFF, 0x01)[(i + phase) % 3] for i in range(width))
            expected_up_row = bytes((a + b) & 0xFF for a, b in zip(filtered_row, previous_row))
            _png_up_filter_in_place(filtered_row, previous_row)
            assert filtered_row == expected_up_row
    sentinel_fixture = (
        "incidental output\n"
        f"{PSRESOURCE_JSON_BEGIN}\n"
        '{"Schema":1,"Items":[],"Warnings":[]}\n'
        f"{PSRESOURCE_JSON_END}\n"
    )
    assert (
        sentinel_json_payload(sentinel_fixture, PSRESOURCE_JSON_BEGIN, PSRESOURCE_JSON_END)[
            "Schema"
        ]
        == 1
    )
    assert normalized_exit_code(-1978335189) == 0x8A15002B
    assert exit_code_hex(-1978335189) == "0x8A15002B"
    assert single_instance_mutex_name().startswith(f"Local\\{APP_NAME}-")
    already_clean = "already clean output"
    assert clean_output(already_clean) is already_clean
    assert clean_output("a\x08b\r\n") == "ab\n"
    assert clean_output("\x1b[31mred\x1b[0m") == "red"
    png_fixture_rows = [
        bytes((12, 34, 56, 255, 78, 90, 123, 128)),
        bytes((210, 180, 150, 64, 0, 0, 0, 0)),
    ]
    assert read_png_rgba(
        rgba_png_bytes(2, 2, png_fixture_rows, compression_level=1)
    ) == (2, 2, png_fixture_rows)
    if os.name == "nt" and os.environ.get("LOCALAPPDATA"):
        alias_fixture = (
            Path(os.environ["LOCALAPPDATA"])
            / "Microsoft"
            / "WindowsApps"
            / "python.exe"
        )
        assert _path_is_windows_app_execution_alias(alias_fixture)
        assert not _path_is_windows_app_execution_alias(Path(r"C:\Program Files\Python\python.exe"))
    redaction_fixture = (
        "Authorization: Bearer abc.def password=hunter2 "
        "https://user:pass@example.invalid/path --token topsecret"
    )
    redacted_fixture = redact_sensitive_text(redaction_fixture)
    assert "abc.def" not in redacted_fixture
    assert "hunter2" not in redacted_fixture
    assert "user:pass" not in redacted_fixture
    assert "topsecret" not in redacted_fixture
    assert redact_log_value({"api_key": "private"})["api_key"] == "[REDACTED]"
    assert redact_sensitive_text("NPM_TOKEN=private") == "NPM_TOKEN=[REDACTED]"
    for redaction_sample in (
        "",
        "ordinary",
        "ordinary-diagnostic-value",
        "two ordinary words",
        "Authorization: Bearer abc.def",
        "--token topsecret",
        "https://user:pass@example.invalid/path",
        r"C:\Users\someone\AppData\Local\Tool",
        "password=hunter2",
    ):
        assert redact_sensitive_text(redaction_sample) == _redact_sensitive_text_full(
            redaction_sample
        )
    assert redact_command_parts(["tool", "--token", "private", "safe"])[1:] == [
        "--token",
        "[REDACTED]",
        "safe",
    ]
    assert redact_command_parts(["tool", "--elevated-authkey", "a" * 64])[-1] == "[REDACTED]"
    assert r"C:\Users\other" not in redact_sensitive_text(
        r"installed at C:\Users\other\AppData\Local\Tool"
    )
    previous_computer_name = os.environ.get("COMPUTERNAME")
    os.environ["COMPUTERNAME"] = "WDP-PRIVATE-HOST"
    try:
        host_redaction = redact_sensitive_text(
            r"host=WDP-PRIVATE-HOST share=\\WDP-PRIVATE-HOST\diagnostics"
        )
        assert "WDP-PRIVATE-HOST" not in host_redaction
        assert host_redaction.count("[COMPUTER]") == 2
    finally:
        if previous_computer_name is None:
            os.environ.pop("COMPUTERNAME", None)
        else:
            os.environ["COMPUTERNAME"] = previous_computer_name
    bounded_fixture = bounded_diagnostic_output("x" * (MAX_DIAGNOSTIC_OUTPUT_CHARS + 100))
    assert bounded_fixture["output_truncated"]
    assert bounded_fixture["output_omitted_chars"] == 100
    installer_log_fixture = winget_installer_log_paths(
        "Installer log is available at: "
        r"C:\Users\tester\AppData\Local\Packages\Microsoft.DesktopAppInstaller_"
        r"8wekyb3d8bbwe\LocalState\DiagOutputDir\Git.Git.2.0.log"
    )
    assert len(installer_log_fixture) == 1
    if os.name == "nt":
        assert installer_log_fixture[0].name == "Git.Git.2.0.log"
    assert "close the listed process" in winget_installer_failure_hint(
        CommandResult(1, "", []),
        [
            {
                "output": "The following process(es) use Git for Windows. "
                "Please terminate those processes and retry."
            }
        ]
    )
    process_fixture = run_capture([sys.executable, "-c", "print('diagnostic-ok')"], timeout=10)
    assert process_fixture.returncode == 0
    assert "diagnostic-ok" in process_fixture.output
    assert process_fixture.process_id and process_fixture.started_at
    assert process_fixture.finished_at and process_fixture.duration_seconds >= 0
    assert process_fixture.process_returncode == 0 and process_fixture.capture_complete
    assert not process_fixture.capture_truncated and not process_fixture.capture_excerpt
    assert process_fixture.capture_bytes and process_fixture.capture_bytes < 100

    # Exact small transcripts and bounded oversized ones, including odd limits
    # and chunks crossing both the head/tail and overflow boundaries.
    for limit in (2, 3, 7, 16):
        for chunk_size in (1, 2, 5, 23):
            for length in range(0, limit * 3):
                payload = bytes(65 + index % 26 for index in range(length))
                buffer = BoundedCommandOutput(limit)
                for offset in range(0, len(payload), chunk_size):
                    buffer.append(payload[offset:offset + chunk_size])
                    assert len(buffer.head) + len(buffer.tail) <= limit
                assert buffer.byte_count == length
                assert buffer.truncated == (length > limit)
                retained = bytes(buffer.head) + buffer.tail_content()
                expected = (
                    payload[:limit // 2] + payload[-(limit - limit // 2):]
                    if length > limit else payload
                )
                assert retained == expected, (limit, chunk_size, length)
                if length <= limit:
                    assert buffer.text() == payload.decode("ascii")
    for payload in (b"", "caf\u00e9 \u03b1 \U0001f642\n".encode(), "version 1.2\n".encode("utf-16")):
        transcript = run_capture(
            [sys.executable, "-c", f"import sys; sys.stdout.buffer.write({payload!r})"],
            timeout=10,
            max_output_bytes=128,
        )
        assert transcript.returncode == 0 and transcript.capture_complete
        assert transcript.output == clean_output(decode_console_output(payload))
        assert transcript.capture_bytes == len(payload)

    oversized_capture = run_capture(
        [sys.executable, "-c", "import sys; "
         "sys.stdout.buffer.write(b'Authorization: Bearer example-token\\n' + b'x'*32768); "
         "sys.stdout.buffer.write(b'\\nfinished-after-overflow\\n'); sys.exit(7)"],
        timeout=10,
        max_output_bytes=512,
    )
    assert oversized_capture.returncode == 125 and oversized_capture.process_returncode == 7
    assert oversized_capture.capture_complete and oversized_capture.capture_truncated
    assert oversized_capture.output == ""  # No parser may consume a partial transcript.
    assert "finished-after-overflow" in oversized_capture.capture_excerpt
    assert len(oversized_capture.capture_excerpt) < 1024
    capture_diagnostics = command_diagnostic_fields(oversized_capture)
    assert capture_diagnostics["capture_limit_bytes"] == 512
    assert capture_diagnostics["output_hash_scope"] == "redacted capture excerpt"
    assert "example-token" not in capture_diagnostics["output"]
    split_credential_capture = BoundedCommandOutput(256)
    split_credential_capture.append(b"Authorization: Bearer " + b"private-fixture" * 100)
    assert "private-fixture" not in split_credential_capture.text()
    assert not NpmProvider().succeeded(oversized_capture)
    assert "verify before retrying" in NpmProvider().status_hint(oversized_capture)

    with patch.dict(globals(), run_capture=lambda *_args, **_kwargs: oversized_capture):
        for provider in (NpmProvider(), RustupProvider(), VcpkgProvider()):
            try:
                provider.discover()
            except RuntimeError as exc:
                assert "capture limit" in str(exc)
            else:
                raise AssertionError(f"{provider.key} accepted incomplete command output")
        winget_capture_probe = WingetProvider()
        assert not winget_capture_probe._installed_inventory_rows("user", allow_recent=False)
        assert winget_capture_probe.warnings

    class BrokenCaptureStream(io.BytesIO):
        def fileno(self) -> int:
            return 123  # Only passed to mocked os functions below.

    class BrokenCaptureProcess:
        pid = 123
        returncode = 0

        def __init__(self) -> None:
            self.stdout = BrokenCaptureStream(b"partial")

        def wait(self, timeout: float) -> int:
            return self.returncode

    with patch.object(os, "set_blocking"), patch.object(
        os, "read", side_effect=[b"partial", OSError("fixture pipe read failure")]
    ), patch.object(
        subprocess, "Popen", return_value=BrokenCaptureProcess()
    ) as ordinary_popen:
        broken_capture = run_capture(["fixture-command"], timeout=10)
    ordinary_flags = int(ordinary_popen.call_args.kwargs["creationflags"])
    assert ordinary_flags & BELOW_NORMAL_PRIORITY_CLASS == 0
    assert broken_capture.returncode == 125 and not broken_capture.capture_complete
    assert not broken_capture.output and broken_capture.capture_excerpt == "partial"
    assert "fixture pipe read failure" in broken_capture.exception
    with background_command_process_priority():
        with patch.object(os, "set_blocking"), patch.object(
            os, "read", side_effect=[b"partial", OSError("fixture pipe read failure")]
        ), patch.object(
            subprocess, "Popen", return_value=BrokenCaptureProcess()
        ) as background_popen:
            run_capture(["fixture-background-command"], timeout=10)
    background_flags = int(background_popen.call_args.kwargs["creationflags"])
    assert background_flags & BELOW_NORMAL_PRIORITY_CLASS
    assert not getattr(_COMMAND_LAUNCH_CONTEXT, "below_normal", False)

    for script in (
        "import sys,time; print('before-timeout', flush=True); time.sleep(5)",
        "import os,time; os.close(1); os.close(2); time.sleep(5)",
    ):
        timed_capture = run_capture([sys.executable, "-c", script], timeout=0.2)
        assert timed_capture.returncode == 124 and timed_capture.timed_out
        assert timed_capture.capture_complete
        assert timed_capture.duration_seconds < 10
    descendant_pipe_capture = run_capture(
        [sys.executable, "-c",
         "import subprocess,sys; subprocess.Popen("
         "[sys.executable, '-c', 'import time; time.sleep(0.8)'], "
         f"stdout=sys.stdout, stderr=sys.stderr, creationflags={CREATE_NO_WINDOW})"],
        timeout=0.2,
    )
    assert not descendant_pipe_capture.timed_out and descendant_pipe_capture.process_returncode == 0
    assert descendant_pipe_capture.capture_complete  # Descendant closes its inherited pipe.
    assert descendant_pipe_capture.duration_seconds < 10
    nonzero_capture = run_capture(
        [sys.executable, "-c", "import sys; print('ordinary-error'); sys.exit(7)"], timeout=10
    )
    assert nonzero_capture.returncode == nonzero_capture.process_returncode == 7
    assert nonzero_capture.output.strip() == "ordinary-error" and not nonzero_capture.exception

    if os.name == "nt":
        assert _SHELL32.IsUserAnAdmin.argtypes == []
        assert _SHELL32.IsUserAnAdmin.restype is wintypes.BOOL
        assert _KERNEL32.CloseHandle.argtypes == [wintypes.HANDLE]
        assert _KERNEL32.CloseHandle.restype is wintypes.BOOL
        assert _user32().MessageBoxW.argtypes == [
            ctypes.c_void_p, ctypes.c_wchar_p, ctypes.c_wchar_p, ctypes.c_uint,
        ]
        assert _user32().MessageBoxW.restype is ctypes.c_int
        assert isinstance(is_admin(), bool)
        assert available_physical_memory_bytes() > 0

        class MemoryProbe:
            argtypes: Any = None
            restype: Any = None
            succeed = True

            def __call__(self, pointer: Any) -> int:
                assert self.restype is ctypes.c_int
                assert self.argtypes == [ctypes.POINTER(type(pointer._obj))]
                assert pointer._obj.dwLength == ctypes.sizeof(pointer._obj)
                pointer._obj.ullAvailPhys = 5 * 1024**3
                return int(self.succeed)

        memory_api = type("MemoryApi", (), {"GlobalMemoryStatusEx": MemoryProbe()})()
        with patch.object(ctypes, "WinDLL", return_value=memory_api):
            assert available_physical_memory_bytes() == 5 * 1024**3
            memory_api.GlobalMemoryStatusEx.succeed = False
            assert available_physical_memory_bytes() == 0
    previous_dotnet_nologo = os.environ.pop("DOTNET_NOLOGO", None)
    previous_dotnet_telemetry = os.environ.pop("DOTNET_CLI_TELEMETRY_OPTOUT", None)
    try:
        dotnet_environment_fixture = run_capture(
            [
                sys.executable,
                "-c",
                (
                    "import json, os; print(json.dumps([os.environ.get('DOTNET_NOLOGO'), "
                    "os.environ.get('DOTNET_CLI_TELEMETRY_OPTOUT')]))"
                ),
            ],
            timeout=10,
        )
    finally:
        if previous_dotnet_nologo is not None:
            os.environ["DOTNET_NOLOGO"] = previous_dotnet_nologo
        if previous_dotnet_telemetry is not None:
            os.environ["DOTNET_CLI_TELEMETRY_OPTOUT"] = previous_dotnet_telemetry
    assert json.loads(dotnet_environment_fixture.output) == ["true", "1"]
    assert portable_signature_for("cpuz_x64.exe").key == "cpu-z"
    assert portable_signature_for("notepad++.exe").key == "notepad-plus-plus"
    assert portable_signature_for("rufus-4.9p.exe").key == "rufus"
    assert portable_signature_for("Chathy.exe").key == "chathy"
    assert portable_signature_for("unrelated.exe") is None
    cpu_z_signature = portable_signature_for("cpuz_x64.exe")
    assert cpu_z_signature is not None
    assert _portable_signature_filename_matches(cpu_z_signature, "cpuz_x64.exe")
    assert not _portable_signature_filename_matches(
        cpu_z_signature, "cpu-z_2.19-en.exe"
    )
    assert not _portable_public_release_url("http://example.com/releases")
    assert not _portable_public_release_url("https://127.0.0.1/releases")
    assert _portable_public_release_url("https://example.com/releases")
    portable_page_item = UpdateItem(
        provider=PORTABLE_PROVIDER_KEY,
        name="Example Portable",
        package_id="portable.example",
        current="1.0",
        available="1.1",
        portable_catalog_homepage="https://example.com/releases",
    )
    assert portable_manual_update_page(portable_page_item) == "https://example.com/releases"
    assert not portable_manual_update_page(
        dataclasses.replace(portable_page_item, portable_catalog_homepage="http://example.com")
    )
    assert _portable_urls_share_declared_host(
        "https://www.example.com/releases",
        "https://example.com/project",
    )
    assert not _portable_urls_share_declared_host(
        "https://downloads.example.net/releases",
        "https://example.com/project",
    )
    github_identity_fixture = PortableRecord(
        app_key="example-tool",
        name="Example Tool",
        version="1.0",
        executable=str(Path.home() / "Tools" / "ExampleTool.exe"),
        icon_source=str(Path.home() / "Tools" / "ExampleTool.exe"),
        scan_root=str(Path.home() / "Tools"),
        detected_by="self-test",
        path_on_path=False,
        original_filename="ExampleTool.exe",
    )
    assert _portable_github_repo_matches_record(
        "https://github.com/example/example-tool/releases",
        github_identity_fixture,
    )
    assert not _portable_github_repo_matches_record(
        "https://github.com/unrelated/lure/releases",
        github_identity_fixture,
    )
    assert portable_homepage_from_nearby_docs(
        github_identity_fixture,
        (
            "https://docs.python.org/",
            "https://github.com/example/example-tool/releases",
        ),
    ) == "https://github.com/example/example-tool/releases"
    assert not portable_homepage_from_nearby_docs(
        github_identity_fixture,
        ("https://docs.python.org/",),
    )
    assert not _portable_release_version_from_text(
        "Latest release 2026.07",
        "8.1",
    )
    assert _portable_release_version_from_text(
        "Current version: 1.3.37",
        "1.3.36",
    ) == "1.3.37"
    assert not _portable_release_version_from_text(
        "A 120-iteration Release 256-to-48 probe improved from 11.46 to 10.45 ms.",
        "1.3.37",
    )
    assert _portable_release_version_from_text(
        "Current app version: 1.3.37\n"
        "Release 256-to-48 probe improved from 11.46 to 10.45 ms.",
        "1.1",
    ) == "1.3.37"
    assert (
        sanitize_windows_version_resource_text("Cinebench 2024\0\0ignored")
        == "Cinebench 2024"
    )
    assert sanitize_windows_version_resource_text("Example\tTool\x01") == "Example Tool"
    assert address_range_within_owned_buffer(1000, 100, 1000, 100)
    assert address_range_within_owned_buffer(1000, 100, 1100, 0)
    assert not address_range_within_owned_buffer(1000, 100, 999, 1)
    assert not address_range_within_owned_buffer(1000, 100, 1001, 100)
    assert not address_range_within_owned_buffer(1000, 100, 1100, 1)
    assert not address_range_within_owned_buffer(1000, 100, 1000, -1)
    if os.name == "nt":
        import winreg

        try:
            for value, kind, expected in (
                (84, winreg.REG_DWORD, 84), (0, winreg.REG_DWORD, 0),
                ("84", winreg.REG_SZ, None), (-1, winreg.REG_DWORD, None),
                (True, winreg.REG_DWORD, None), (2**32, winreg.REG_DWORD, None),
            ):
                system_boot_id.cache_clear()
                with patch.object(winreg, "OpenKey") as opened, patch.object(
                    winreg, "QueryValueEx", return_value=(value, kind),
                ) as queried:
                    assert system_boot_id() == expected
                    assert system_boot_id() == expected
                    assert opened.call_count == queried.call_count == 1
            system_boot_id.cache_clear()
            with patch.object(winreg, "OpenKey", side_effect=PermissionError("fixture")) as opened:
                assert system_boot_id() is None
                assert system_boot_id() is None
                assert opened.call_count == 1
        finally:
            system_boot_id.cache_clear()
    assert not portable_catalog_metadata_is_fresh(
        dataclasses.replace(
            github_identity_fixture,
            catalog_available_version="11.46",
            catalog_match_basis="newer version stated in nearby release documentation",
            catalog_checked_at=utc_now_iso(),
        )
    )
    release_document_fixture = dataclasses.replace(
        github_identity_fixture,
        executable=str(Path.home() / "Tools" / "ExampleTool" / "bin" / "ExampleTool.exe"),
    )
    assert _portable_release_document_is_app_owned(
        release_document_fixture,
        Path.home() / "Tools" / "ExampleTool" / "README.md",
    )
    assert not _portable_release_document_is_app_owned(
        release_document_fixture,
        Path.home() / "Tools" / "README.md",
    )
    if os.name == "nt":
        class OutOfRangeVersionApi:
            def __init__(self, oversized_length: bool = False) -> None:
                self.buffer_start = 0
                self.buffer_size = 0
                self.oversized_length = oversized_length

            def GetFileVersionInfoSizeW(self, *_args: Any) -> int:
                return 128

            def GetFileVersionInfoW(
                self,
                _filename: str,
                _handle: int,
                size: int,
                buffer: Any,
            ) -> int:
                self.buffer_start = ctypes.addressof(buffer)
                self.buffer_size = size
                return 1

            def VerQueryValueW(
                self,
                _buffer: Any,
                _sub_block: str,
                pointer_output: Any,
                length_output: Any,
            ) -> int:
                if self.oversized_length:
                    if _sub_block == "\\":
                        return 0
                    pointer_output._obj.value = self.buffer_start + 4
                    length_output._obj.value = 256
                else:
                    pointer_output._obj.value = self.buffer_start + self.buffer_size + 1
                    length_output._obj.value = 52
                return 1

        original_version_api = globals()["_windows_version_api"]
        try:
            for oversized_length in (False, True):
                globals()["_windows_version_api"] = lambda: OutOfRangeVersionApi(oversized_length)
                with (
                    patch.object(ctypes, "string_at", side_effect=AssertionError("invalid byte range")),
                    patch.object(ctypes, "wstring_at", side_effect=AssertionError("invalid text range")),
                ):
                    assert not windows_file_version_strings("out-of-range-version-fixture.exe")
        finally:
            globals()["_windows_version_api"] = original_version_api
        interpreter_version = windows_file_version_strings(sys.executable)
        assert interpreter_version.get("FixedFileVersion")
        assert interpreter_version.get("OriginalFilename")
        assert portable_pe_subsystem(sys.executable) in {2, 3}
        drive_root = Path(Path.home().anchor)
        assert portable_scan_is_broad_root(drive_root)
        assert portable_broad_directory_rejection(
            Path.home() / "AppData", drive_root
        )
        assert portable_broad_directory_rejection(
            Path.home().parent / "OtherAccount" / "Downloads", drive_root
        )
    generic_metadata = {
        "ProductName": "Open Hardware Monitor",
        "CompanyName": "Open Hardware Monitor Project",
        "FileDescription": "Open Hardware Monitor",
        "OriginalFilename": "OpenHardwareMonitor.exe",
        "FixedProductVersion": "0.9.6.0",
    }
    with tempfile.TemporaryDirectory() as portable_tmp:
        portable_root = Path(portable_tmp)
        original_reparse_probe = globals()["_portable_path_is_reparse_point"]
        try:
            globals()["_portable_path_is_reparse_point"] = (
                lambda path: Path(path).absolute() == portable_root.absolute()
            )
            assert "link or junction" in portable_scan_root_rejection(portable_root)
        finally:
            globals()["_portable_path_is_reparse_point"] = original_reparse_probe
        expected_portables = (
            portable_root / "CPU-Z" / "cpuz_x64.exe",
            portable_root / "Notepad++" / "notepad++.exe",
            portable_root / "Rufus" / "rufus-4.9p.exe",
            portable_root / "Chathy" / "Chathy.exe",
        )
        for executable in expected_portables:
            executable.parent.mkdir(parents=True, exist_ok=True)
            executable.write_bytes(b"portable-fixture")
        nearby_payload = expected_portables[0].parent / "cpuz.ini"
        nearby_payload.write_bytes(b"portable-neighbor-fixture")
        (
            portable_date,
            portable_timestamp,
            portable_date_source,
            portable_date_evidence,
        ) = portable_executable_service_date(
            expected_portables[0],
            app_name="CPU-Z",
            scan_root=portable_root,
        )
        assert re.fullmatch(r"\d{4}-\d{2}-\d{2}", portable_date)
        assert normalize_wall_clock_timestamp(portable_timestamp)[1] == "fractional-6"
        assert "approximate" in portable_date_source
        assert str(expected_portables[0]) in portable_date_evidence
        if os.name == "nt":
            assert "Corroborated" in portable_date_source
            assert str(expected_portables[0].parent) in portable_date_evidence
            assert str(nearby_payload) in portable_date_evidence
        with tempfile.TemporaryDirectory() as shared_tmp:
            shared_folder = Path(shared_tmp) / "Utilities"
            shared_folder.mkdir()
            loose_executable = shared_folder / "rufus.exe"
            loose_executable.write_bytes(b"portable-shared-folder-fixture")
            (
                shared_date,
                shared_timestamp,
                shared_source,
                shared_evidence,
            ) = portable_executable_service_date(
                loose_executable,
                app_name="Rufus",
                scan_root=shared_tmp,
            )
            assert shared_date
            assert normalize_wall_clock_timestamp(shared_timestamp)[1] == "fractional-6"
            assert "Corroborated" not in shared_source
            assert shared_evidence == (str(loose_executable),)
            shared_stat = loose_executable.stat()
            equal_time = shared_stat.st_mtime
            with patch.object(Path, "stat", return_value=SimpleNamespace(
                st_birthtime=equal_time, st_ctime=equal_time, st_mtime=equal_time,
                st_file_attributes=0, st_mode=shared_stat.st_mode,
            )):
                equal_date, equal_timestamp, equal_source, equal_evidence = portable_executable_service_date(
                    loose_executable, app_name="Rufus", scan_root=shared_folder,
                )
            assert equal_date == dt.datetime.fromtimestamp(equal_time).date().isoformat()
            assert normalize_wall_clock_timestamp(equal_timestamp)[1] == "fractional-6"
            assert "filesystem creation time" in equal_source
            assert equal_evidence == (str(loose_executable),)
        with tempfile.TemporaryDirectory() as single_app_tmp:
            single_app_root = Path(single_app_tmp) / "Rufus"
            single_app_root.mkdir()
            single_app_executable = single_app_root / "rufus.exe"
            single_app_payload = single_app_root / "rufus.ini"
            single_app_executable.write_bytes(b"portable-single-app-fixture")
            single_app_payload.write_bytes(b"portable-single-app-neighbor")
            (
                single_app_date,
                single_app_timestamp,
                single_app_source,
                single_app_evidence,
            ) = portable_executable_service_date(
                single_app_executable,
                app_name="Rufus",
                scan_root=single_app_root,
            )
            assert single_app_date
            assert normalize_wall_clock_timestamp(single_app_timestamp)[1] == "fractional-6"
            if os.name == "nt":
                assert "Corroborated" in single_app_source
                assert str(single_app_root) in single_app_evidence
                assert str(single_app_executable) in single_app_evidence
        (expected_portables[0].parent / "unrelated.png").write_bytes(b"not-an-icon-fixture")
        pruned_executable = portable_root / "node_modules" / "Rufus" / "rufus.exe"
        pruned_executable.parent.mkdir(parents=True)
        pruned_executable.write_bytes(b"must-not-be-seen")
        portable_progress: list[PortableScanProgress] = []
        portable_result = scan_portable_root(
            portable_root,
            progress_callback=portable_progress.append,
            progress_interval_seconds=0,
        )
        assert portable_progress
        assert all(progress.root == str(portable_root) for progress in portable_progress)
        assert {record.app_key for record in portable_result.records} == {
            "cpu-z",
            "notepad-plus-plus",
            "rufus",
            "chathy",
        }
        assert len(portable_result.records) == 4
        assert not portable_result.truncated
        cpu_record = next(
            record for record in portable_result.records if record.app_key == "cpu-z"
        )
        assert Path(cpu_record.icon_source) == expected_portables[0]
        assert executable_folder_on_path(
            cpu_record.executable, str(Path(cpu_record.executable).parent)
        )
        assert not executable_folder_on_path(cpu_record.executable, str(portable_root))
        cache_path = portable_root / "cache" / PORTABLE_CACHE_FILENAME
        portable_store = PortableInventoryStore(cache_path)
        portable_store.replace_root(portable_result)
        reloaded_store = PortableInventoryStore(cache_path)
        assert len(reloaded_store.records()) == 4
        assert reloaded_store.roots() == (str(portable_root),)
        cached_date_value = "2026-08-30"
        cached_timestamp_value = "2026-08-30T12:34:56.123456+00:00"
        cached_date_source = "Corroborated portable file dates (approximate)"
        cached_date_paths = (
            str(expected_portables[0]),
            str(expected_portables[0].parent),
        )
        assert reloaded_store.update_date_evidence(
            {
                str(expected_portables[0]): (
                    cached_date_value,
                    cached_timestamp_value,
                    "fractional-6",
                    cached_date_source,
                    cached_date_paths,
                )
            }
        ) == 1
        cached_cpu_record = next(
            record
            for record in PortableInventoryStore(cache_path).records()
            if record.app_key == "cpu-z"
        )
        assert portable_record_date_evidence(cached_cpu_record) == (
            cached_date_value,
            cached_timestamp_value,
            "fractional-6",
            cached_date_source,
            cached_date_paths,
        )
        expected_portables[0].write_bytes(b"portable-fixture-changed")
        assert portable_record_date_evidence(cached_cpu_record) == ("", "", "", "", ())
        assert reloaded_store.update_date_evidence(
            {
                str(expected_portables[0]): (
                    cached_date_value,
                    cached_timestamp_value,
                    "fractional-6",
                    cached_date_source,
                    cached_date_paths,
                )
            }
        ) == 1
        clear_cache_path = portable_root / "clear-cache" / PORTABLE_CACHE_FILENAME
        clear_store = PortableInventoryStore(clear_cache_path)
        clear_store.replace_root(portable_result)
        stale_records, stale_revision = clear_store.catalog_snapshot()
        assert clear_cache_path.is_file()
        assert clear_store.clear() == (4, 1)
        assert (
            clear_store.update_records(
                stale_records,
                expected_revision=stale_revision,
            )
            is None
        )
        assert not clear_store.records()
        assert not clear_store.roots()
        assert not clear_cache_path.exists()
        catalog_only_update = dataclasses.replace(
            cpu_record,
            version="must-not-replace-local-version",
            catalog_package_id="CPUID.CPU-Z",
            catalog_available_version="2.20",
            catalog_checked_at=utc_now_iso(),
        )
        assert reloaded_store.update_records((catalog_only_update,)) == 1
        refreshed_cpu_record = next(
            record
            for record in reloaded_store.records()
            if record.app_key == "cpu-z"
        )
        assert refreshed_cpu_record.version == cpu_record.version
        assert refreshed_cpu_record.catalog_available_version == "2.20"
        local_snapshot, local_revision = reloaded_store.catalog_snapshot()
        locally_reprobed = tuple(
            dataclasses.replace(record, version="9.9")
            if record.app_key == "cpu-z"
            else record
            for record in local_snapshot
        )
        assert (
            reloaded_store.update_local_records(
                locally_reprobed,
                expected_revision=local_revision,
            )
            == 1
        )
        refreshed_cpu_record = next(
            record
            for record in reloaded_store.records()
            if record.app_key == "cpu-z"
        )
        assert refreshed_cpu_record.version == "9.9"
        assert refreshed_cpu_record.catalog_available_version == "2.20"
        portable_item = portable_record_to_item(cpu_record)
        assert portable_item.provider == PORTABLE_PROVIDER_KEY
        assert not portable_item.selected
        assert portable_item.classification == CLASS_INVENTORY_ONLY
        assert portable_item.portable_executable == cpu_record.executable
        assert launchable_executable(portable_item) == expected_portables[0].resolve()
        executable_route = app_run_route(portable_item)
        assert executable_route == AppRunRoute(
            "executable", expected_portables[0].resolve()
        )
        with patch(f"{__name__}.portable_pe_subsystem", return_value=2), patch(
            f"{__name__}.os.startfile", create=True,
        ) as startfile:
            activate_app_route(executable_route)
            startfile.assert_called_once_with(
                executable_route.target, cwd=str(executable_route.target.parent),
            )
        assert app_containing_folder(portable_item, executable_route) == expected_portables[
            0
        ].resolve().parent
        assert portable_item.available == "Not checked"
        assert portable_item.portable_removal_kind == "folder"
        assert WinDevPilotApp._display_package_id(portable_item).startswith(
            "portable.cpu-z…"
        )
        assert len(WinDevPilotApp._display_package_id(portable_item).rsplit("…", 1)[-1]) == 8
        generic_display_item = dataclasses.replace(
            portable_item,
            package_id="portable.generic-6820c789744286bd7a1c.d73a2f1b42f219eb",
        )
        assert (
            WinDevPilotApp._display_package_id(generic_display_item)
            == "portable.generic…42f219eb"
        )
        assert WinDevPilotApp._display_status(portable_item).startswith("Portable")
        assert "Executable folder on PATH" in WinDevPilotApp.status_tooltip_text(
            portable_item
        )
        catalog_portable_item = dataclasses.replace(
            portable_item,
            available="2.20",
            portable_catalog_package_id="CPUID.CPU-Z",
            portable_catalog_match_basis="curated CPU-Z executable signature",
            portable_catalog_checked_at=utc_now_iso(),
        )
        catalog_portable_tooltip = WinDevPilotApp.status_tooltip_text(
            catalog_portable_item
        )
        assert "Match basis: curated CPU-Z executable signature" in catalog_portable_tooltip
        portable_details_probe = object.__new__(WinDevPilotApp)
        portable_details_probe.providers = {
            PORTABLE_PROVIDER_KEY: PortableProvider()
        }
        portable_details_probe.settings = SettingsStore(
            portable_root / "portable-details-settings.json"
        )
        portable_details_probe.debug_mode = False
        portable_details_probe.process_is_admin = False
        ordinary_portable_details = WinDevPilotApp.item_details_text(
            portable_details_probe,
            portable_item,
        )
        assert "Portable installation" in ordinary_portable_details
        assert "  Evidence:" not in ordinary_portable_details
        portable_details_probe.debug_mode = True
        debug_portable_details = WinDevPilotApp.item_details_text(
            portable_details_probe,
            portable_item,
        )
        assert "  Evidence:" in debug_portable_details
        loose_folder = portable_root / "GrabBag"
        loose_folder.mkdir()
        loose_rufus = loose_folder / "rufus-4.9p.exe"
        loose_neighbor = loose_folder / "notes.txt"
        loose_rufus.write_bytes(b"rufus")
        loose_neighbor.write_text("keep me", encoding="utf-8")
        loose_plan = portable_removal_plan(
            app_key="rufus",
            executable=loose_rufus,
            scan_root=portable_root,
        )
        assert loose_plan is not None and loose_plan.kind == "file"
        loose_item = portable_record_to_item(
            PortableRecord(
                app_key="rufus",
                name="Rufus",
                version="4.9",
                executable=str(loose_rufus),
                icon_source=str(loose_rufus),
                scan_root=str(portable_root),
                detected_by="self-test",
                path_on_path=False,
            )
        )
        loose_result = remove_portable_item(loose_item)
        assert loose_result.returncode == 0
        assert not loose_rufus.exists()
        assert loose_neighbor.is_file()
        safe_folder = portable_root / "Notepad++ Safe"
        safe_executable = safe_folder / "notepad++.exe"
        safe_helper = safe_folder / "updater" / "gup.exe"
        safe_helper.parent.mkdir(parents=True)
        safe_executable.write_bytes(b"notepad")
        safe_helper.write_bytes(b"helper")
        safe_item = portable_record_to_item(
            PortableRecord(
                app_key="notepad-plus-plus",
                name="Notepad++",
                version="8.9.7",
                executable=str(safe_executable),
                icon_source=str(safe_executable),
                scan_root=str(portable_root),
                detected_by="self-test",
                path_on_path=False,
            )
        )
        assert safe_item.portable_removal_kind == "folder"
        safe_result = remove_portable_item(safe_item)
        assert safe_result.returncode == 0
        assert not safe_folder.exists()
        ambiguous_folder = portable_root / "CPU-Z bundle"
        ambiguous_executable = ambiguous_folder / "cpuz_x64.exe"
        ambiguous_executable.parent.mkdir()
        ambiguous_executable.write_bytes(b"cpuz")
        (ambiguous_folder / "other-app.exe").write_bytes(b"other")
        assert (
            portable_removal_plan(
                app_key="cpu-z",
                executable=ambiguous_executable,
                scan_root=portable_root,
            )
            is None
        )
        guarded_folder = portable_root / "Rufus guarded"
        guarded_executable = guarded_folder / "rufus.exe"
        guarded_folder.mkdir()
        guarded_executable.write_bytes(b"rufus")
        guarded_item = portable_record_to_item(
            PortableRecord(
                app_key="rufus",
                name="Rufus",
                version="4.9",
                executable=str(guarded_executable),
                icon_source=str(guarded_executable),
                scan_root=str(portable_root),
                detected_by="self-test",
                path_on_path=False,
            )
        )
        assert guarded_item.portable_removal_kind == "folder"
        (guarded_folder / "arrived-later.exe").write_bytes(b"other")
        guarded_result = remove_portable_item(guarded_item)
        assert guarded_result.returncode != 0
        assert guarded_folder.is_dir()
        outside_root = portable_root.parent / f"{portable_root.name}-outside-rufus.exe"
        outside_root.write_bytes(b"outside")
        try:
            assert (
                portable_removal_plan(
                    app_key="rufus",
                    executable=outside_root,
                    scan_root=portable_root,
                )
                is None
            )
        finally:
            outside_root.unlink()
        assert reloaded_store.forget_executable(expected_portables[3])
        assert reloaded_store.forget_executables(
            (expected_portables[1], expected_portables[2], expected_portables[2])
        ) == 2
        assert len(PortableInventoryStore(cache_path).records()) == 1
        assert all(path.is_file() for path in expected_portables)

        def catalog_runner(command: list[str], *, timeout: int) -> CommandResult:
            assert timeout > 0
            if command[1] == "show":
                package_id = command[command.index("--id") + 1]
                return CommandResult(
                    0,
                    (
                        f"Found {package_id} [{package_id}]\n"
                        f"Version: {'4.15' if package_id == 'Rufus.Rufus' else '1.2.3'}\n"
                        f"Name: {'Rufus' if package_id == 'Rufus.Rufus' else 'Chathy'}\n"
                        "Homepage: https://example.invalid/home\n"
                        "Installer URL: https://example.invalid/download.exe\n"
                    ),
                    command,
                )
            assert command[1] == "search"
            return CommandResult(
                0,
                (
                    "Name   Id             Version Source\n"
                    "------------------------------------\n"
                    "Chathy Example.Chathy 1.2.3   winget\n"
                ),
                command,
            )

        catalog_rufus = refresh_portable_catalog_record(
            dataclasses.replace(
                cpu_record,
                app_key="rufus",
                name="Rufus",
            ),
            runner=catalog_runner,
        )
        assert catalog_rufus.catalog_package_id == "Rufus.Rufus"
        assert catalog_rufus.catalog_available_version == "4.15"
        assert catalog_rufus.catalog_homepage == "https://example.invalid/home"
        assert catalog_rufus.catalog_download_url == "https://example.invalid/download.exe"
        portable_update_advisory = portable_record_to_update_item(
            dataclasses.replace(
                catalog_rufus,
                version="4.14",
                catalog_available_version="4.15",
            )
        )
        assert portable_update_advisory is not None
        assert WinDevPilotApp._item_is_actionable(portable_update_advisory)
        assert not WinDevPilotApp._item_is_bulk_selectable(portable_update_advisory)
        portable_update_advisory.selected = True
        assert portable_update_advisory.selected
        try:
            PortableProvider().build_update_command(portable_update_advisory)
        except ValueError as exc:
            assert "detection-only" in str(exc)
        else:
            raise AssertionError("portable provider unexpectedly built an update command")
        portable_boundary_probe = object.__new__(WinDevPilotApp)
        portable_boundary_probe.busy = False
        refused_portables: list[tuple[UpdateItem, ...]] = []
        started_batches: list[tuple[UpdateItem, ...]] = []
        portable_boundary_probe._explain_manual_portable_updates = (
            lambda items: refused_portables.append(tuple(items))
        )
        portable_boundary_probe._confirm_update_batch = (
            lambda items, **_kwargs: started_batches.append(tuple(items))
        )
        portable_boundary_probe._continue_update_selected([portable_update_advisory])
        assert refused_portables == [(portable_update_advisory,)]
        assert not started_batches
        catalog_chathy = refresh_portable_catalog_record(
            dataclasses.replace(
                cpu_record,
                app_key="chathy",
                name="Chathy",
            ),
            runner=catalog_runner,
        )
        assert catalog_chathy.catalog_package_id == "Example.Chathy"
        assert catalog_chathy.catalog_available_version == "1.2.3"

        def ambiguous_catalog_runner(
            command: list[str], *, timeout: int
        ) -> CommandResult:
            assert command[1] == "search" and timeout > 0
            return CommandResult(
                0,
                (
                    "Name   Id             Version Source\n"
                    "------------------------------------\n"
                    "Chathy Example.Chathy 1.2.3   winget\n"
                    "Chathy Other.Chathy   2.0.0   winget\n"
                ),
                command,
            )

        ambiguous_catalog = refresh_portable_catalog_record(
            dataclasses.replace(
                cpu_record,
                app_key="chathy",
                name="Chathy",
            ),
            runner=ambiguous_catalog_runner,
        )
        assert not ambiguous_catalog.catalog_package_id
        assert "multiple" in ambiguous_catalog.catalog_error
        assert portable_record_to_item(ambiguous_catalog).available == "Not found"

        generic_catalog_record = PortableRecord(
            app_key="generic-self-test",
            name="Example Portable",
            version="1.0",
            executable=str(expected_portables[0]),
            icon_source=str(expected_portables[0]),
            scan_root=str(portable_root),
            detected_by="self-test",
            path_on_path=False,
            publisher="Example Publisher",
            original_filename="ExamplePortable.exe",
            detection_confidence="high",
            evidence_score=110,
            evidence_reasons=("self-test evidence",),
            portable_format="generic PE portable",
        )

        def generic_catalog_runner(
            command: list[str], *, timeout: int
        ) -> CommandResult:
            assert timeout > 0
            if command[1] == "search":
                return CommandResult(
                    0,
                    (
                        f"{'Name':<25}{'Id':<32}{'Version':<10}Source\n"
                        f"{'-' * 24:<25}{'-' * 31:<32}{'-' * 9:<10}{'-' * 6}\n"
                        f"{'Example Portable':<25}{'Example.ExamplePortable':<32}{'2.0':<10}winget\n"
                    ),
                    command,
                )
            assert command[1] == "show"
            return CommandResult(
                0,
                (
                    "Found Example Portable [Example.ExamplePortable]\n"
                    "Version: 2.0\n"
                    "Publisher: Example Publisher LLC\n"
                    "Nested Installer Type: portable\n"
                    "Homepage: https://example.invalid/portable\n"
                ),
                command,
            )

        generic_catalog = refresh_portable_catalog_record(
            generic_catalog_record,
            runner=generic_catalog_runner,
        )
        assert generic_catalog.catalog_package_id == "Example.ExamplePortable"
        assert generic_catalog.catalog_available_version == "2.0"
        assert "manifest declares portable" in generic_catalog.catalog_match_basis

        def nonportable_catalog_runner(
            command: list[str], *, timeout: int
        ) -> CommandResult:
            result = generic_catalog_runner(command, timeout=timeout)
            if command[1] == "show":
                return dataclasses.replace(
                    result,
                    output=result.output.replace(
                        "Nested Installer Type: portable",
                        "Installer Type: exe",
                    ),
                )
            return result

        rejected_generic_catalog = refresh_portable_catalog_record(
            generic_catalog_record,
            runner=nonportable_catalog_runner,
        )
        assert not rejected_generic_catalog.catalog_package_id
        assert "did not declare a portable" in rejected_generic_catalog.catalog_error
    with tempfile.TemporaryDirectory() as verification_tmp:
        verification_root = Path(verification_tmp)
        live_executable = verification_root / "Live.exe"
        missing_executable = verification_root / "Missing.exe"
        live_executable.write_bytes(b"live")
        verification_store = PortableInventoryStore(
            verification_root / PORTABLE_CACHE_FILENAME
        )
        verification_store.replace_root(
            PortableScanResult(
                root=str(verification_root),
                records=(
                    PortableRecord(
                        app_key="live",
                        name="Live",
                        version="1",
                        executable=str(live_executable),
                        icon_source=str(live_executable),
                        scan_root=str(verification_root),
                        detected_by="self-test",
                        path_on_path=False,
                    ),
                    PortableRecord(
                        app_key="missing",
                        name="Missing",
                        version="1",
                        executable=str(missing_executable),
                        icon_source=str(missing_executable),
                        scan_root=str(verification_root),
                        detected_by="self-test",
                        path_on_path=False,
                    ),
                ),
                files_checked=2,
                directories_checked=1,
                metadata_probes=0,
                access_errors=0,
                truncated=False,
                duration_seconds=0.0,
            )
        )
        assert len(verification_store.records()) == 2
        verification = verification_store.verify_records()
        assert verification.pruned_records == 1
        assert [record.app_key for record in verification.records] == ["live"]
        assert len(PortableInventoryStore(verification_store.path).records()) == 1

    with tempfile.TemporaryDirectory() as generic_tmp:
        generic_root = Path(generic_tmp)
        generic_executable = (
            generic_root / "OpenHardwareMonitor" / "OpenHardwareMonitor.exe"
        )
        generic_executable.parent.mkdir()
        generic_executable.write_bytes(b"generic-portable-fixture")
        generic_evidence = portable_generic_evidence(
            generic_executable,
            generic_metadata,
            WindowsInstalledInventory.empty(),
            scan_root=generic_root,
            broad_scan=False,
        )
        assert generic_evidence.confidence == "high"
        assert generic_evidence.score >= 105
        broad_evidence = portable_generic_evidence(
            generic_executable,
            generic_metadata,
            WindowsInstalledInventory.empty(),
            scan_root=Path(generic_root.anchor),
            broad_scan=True,
        )
        assert broad_evidence.confidence == "review"
        broad_container_evidence = portable_generic_evidence(
            generic_root
            / "Utilities"
            / "OpenHardwareMonitor"
            / "OpenHardwareMonitor.exe",
            generic_metadata,
            WindowsInstalledInventory.empty(),
            scan_root=Path(generic_root.anchor),
            broad_scan=True,
        )
        assert broad_container_evidence.confidence == "high"
        broad_installer_like_evidence = portable_generic_evidence(
            generic_root / "Utilities" / "ExampleTool-2.0-x64.exe",
            {
                "ProductName": "ExampleTool",
                "CompanyName": "Example Publisher",
                "FileDescription": "ExampleTool",
                "OriginalFilename": "",
            },
            WindowsInstalledInventory.empty(),
            scan_root=Path(generic_root.anchor),
            broad_scan=True,
        )
        assert broad_installer_like_evidence.confidence == "review"
        bounded_single_file_evidence = portable_generic_evidence(
            generic_root / "Utilities" / "ExampleTool-2.0-x64.exe",
            {
                "ProductName": "ExampleTool",
                "CompanyName": "Example Publisher",
                "FileDescription": "ExampleTool",
                "OriginalFilename": "",
            },
            WindowsInstalledInventory.empty(),
            scan_root=generic_root / "Utilities",
            broad_scan=False,
        )
        assert bounded_single_file_evidence.confidence == "high"
        installed_convention_evidence = portable_generic_evidence(
            Path.home()
            / "AppData"
            / "Local"
            / "Programs"
            / "OpenHardwareMonitor"
            / "OpenHardwareMonitor.exe",
            generic_metadata,
            WindowsInstalledInventory.empty(),
            scan_root=generic_root,
            broad_scan=False,
        )
        assert installed_convention_evidence.confidence == "rejected"
        unpublished_evidence = portable_generic_evidence(
            generic_executable,
            {key: value for key, value in generic_metadata.items() if key != "CompanyName"},
            WindowsInstalledInventory.empty(),
            scan_root=generic_root,
            broad_scan=False,
        )
        assert unpublished_evidence.confidence == "review"
        exact_folder_evidence = portable_generic_evidence(
            generic_executable,
            {key: value for key, value in generic_metadata.items() if key != "CompanyName"},
            WindowsInstalledInventory.empty(),
            scan_root=generic_executable.parent,
            broad_scan=False,
        )
        assert exact_folder_evidence.confidence == "high"
        assert "exact folder selected" in " ".join(exact_folder_evidence.reasons)
        desktopking_evidence = portable_generic_evidence(
            generic_root / "DesktopKing" / "desktopking.exe",
            {
                "ProductName": "DesktopKing",
                "CompanyName": "DesktopKing",
                "FileDescription": "DesktopKing Utility",
                "OriginalFilename": "desktopking.exe",
            },
            WindowsInstalledInventory.empty(),
            scan_root=generic_root,
            broad_scan=False,
        )
        assert desktopking_evidence.confidence == "high"
        mousetester_evidence = portable_generic_evidence(
            generic_root / "MouseTester" / "MouseTester.exe",
            {
                "ProductName": "MouseTester",
                "FileDescription": "MouseTester",
                "OriginalFilename": "MouseTester.exe",
            },
            WindowsInstalledInventory.empty(),
            scan_root=generic_root,
            broad_scan=False,
        )
        assert mousetester_evidence.confidence == "review"
        marked_executable = generic_root / "MarkedTool" / "MarkedTool.exe"
        marked_executable.parent.mkdir()
        marked_executable.write_bytes(b"portable-marker-fixture")
        (marked_executable.parent / "portable.dat").write_bytes(b"")
        marked_evidence = portable_generic_evidence(
            marked_executable,
            {
                "ProductName": "MarkedTool",
                "FileDescription": "MarkedTool",
                "OriginalFilename": "MarkedTool.exe",
            },
            WindowsInstalledInventory.empty(),
            scan_root=generic_root,
            broad_scan=False,
        )
        assert marked_evidence.confidence == "high"
        assert any("portable.dat" in reason for reason in marked_evidence.reasons)
        (generic_executable.parent / "README.md").write_text(
            (
                "Open Hardware Monitor\n\n"
                "Latest release: 1.0.0\n"
                "Project: https://github.com/example/open-hardware-monitor\n"
            ),
            encoding="utf-8",
        )
        local_release_clue = refresh_portable_release_clue(
            PortableRecord(
                app_key="generic-openhardwaremonitor",
                name="Open Hardware Monitor",
                version="0.9.6",
                executable=str(generic_executable),
                icon_source=str(generic_executable),
                scan_root=str(generic_root),
                detected_by="self-test",
                path_on_path=False,
                publisher="Open Hardware Monitor Project",
                original_filename="OpenHardwareMonitor.exe",
                detection_confidence="high",
                evidence_score=110,
                evidence_reasons=("self-test evidence",),
                portable_format="generic PE portable",
            )
        )
        assert local_release_clue.catalog_available_version == "1.0.0"
        assert "nearby release documentation" in local_release_clue.catalog_match_basis
        assert local_release_clue.catalog_homepage.startswith("https://github.com/")
        installer_evidence = portable_generic_evidence(
            generic_root / "OpenHardwareMonitor-setup.exe",
            generic_metadata,
            WindowsInstalledInventory.empty(),
            scan_root=generic_root,
            broad_scan=False,
        )
        assert installer_evidence.confidence == "rejected"
        self_extracting_installer = (
            generic_root / "Installers" / "Thunderbird Beta Latest win64.exe"
        )
        sfx_evidence = portable_generic_evidence(
            self_extracting_installer,
            {
                "ProductName": "Thunderbird\0\0padding",
                "CompanyName": "Mozilla",
                "FileDescription": "Thunderbird installer",
                "OriginalFilename": "7zS.sfx.exe\0\0padding",
            },
            WindowsInstalledInventory.empty(),
            scan_root=generic_root,
            broad_scan=False,
        )
        assert sfx_evidence.confidence == "rejected"
        assert PortableRecord.from_json(
            {
                "app_key": "generic-thunderbird-installer",
                "name": "Thunderbird\0\0padding",
                "version": "18.5",
                "executable": str(self_extracting_installer),
                "icon_source": str(self_extracting_installer),
                "scan_root": str(generic_root),
                "detected_by": "cached folder scan",
                "path_on_path": False,
                "publisher": "Mozilla",
                "original_filename": "7zS.sfx.exe\0\0padding",
                "detection_confidence": "high",
                "evidence_score": 110,
                "evidence_reasons": ["legacy cache fixture"],
                "portable_format": "generic PE portable",
            },
            str(generic_root),
        ) is None
        registered_evidence = portable_generic_evidence(
            generic_executable,
            generic_metadata,
            WindowsInstalledInventory(
                [
                    RegistryInstallEntry(
                        display_name="Open Hardware Monitor",
                        display_version="0.9.6",
                        scope="user",
                        technology="exe",
                        install_location=str(generic_executable.parent),
                    )
                ]
            ),
            scan_root=generic_root,
            broad_scan=False,
        )
        assert registered_evidence.confidence == "rejected"
        installed_root = generic_root / "Registered App"
        uninstaller_root = generic_root / "Uninstaller Only"
        uninstaller_root.mkdir()
        uninstaller = uninstaller_root / "uninstall.exe"
        uninstaller.write_bytes(b"never executed")
        icon_file = generic_root / "Shared Icons" / "app.exe"
        registration_inventory = WindowsInstalledInventory([
            RegistryInstallEntry("Registered", "1", "user", "exe",
                                 install_location=str(installed_root)),
            RegistryInstallEntry("Icon only", "1", "user", "exe",
                                 display_icon=f'"{icon_file}",0'),
            RegistryInstallEntry("Uninstaller only", "1", "user", "exe",
                                 uninstall_command=f'"{uninstaller}" /quiet'),
        ])
        with patch.dict(globals(), local_executable_from_command=Mock(
            wraps=local_executable_from_command
        )):
            registration_index = PortableInstalledRegistrationIndex.from_inventory(
                registration_inventory
            )
            parse_count = local_executable_from_command.call_count
            for candidate, expected in (
                (installed_root / "bin" / "deep" / "app.exe", True),
                (installed_root, True),
                (generic_root / "Registered App Extra" / "app.exe", False),
                (icon_file, True),
                (icon_file.parent / "unrelated.exe", False),
                (uninstaller, True),
                (uninstaller_root / "bin" / "deep" / "app.exe", True),
                (generic_root / "Uninstaller Only Extra" / "app.exe", False),
            ):
                assert registration_index.contains(candidate) is expected, candidate
            assert local_executable_from_command.call_count == parse_count
        assert portable_generic_evidence(
            generic_executable, generic_metadata, registration_index,
            scan_root=generic_root, broad_scan=False,
        ) == portable_generic_evidence(
            generic_executable, generic_metadata, registration_inventory,
            scan_root=generic_root, broad_scan=False,
        )
        # Index lifetime is one scan. A later snapshot sees changed registration.
        assert not PortableInstalledRegistrationIndex.from_inventory(
            WindowsInstalledInventory.empty()
        ).contains(installed_root / "app.exe")
        if os.name == "nt":
            for registered_folder in (
                Path("C:/"), Path("//server/share/"), Path.home(), Path.home().parent,
                Path.home().parent / "OtherAccount", *portable_system_install_roots(),
                generic_root / "Tools", generic_root / "PortableApps",
                generic_root / "Portable Apps",
            ):
                broad_index = PortableInstalledRegistrationIndex.from_inventory(
                    WindowsInstalledInventory([
                        RegistryInstallEntry("Broad registration", "1", "machine", "exe",
                                             install_location=str(registered_folder)),
                    ])
                )
                assert not broad_index.contains(registered_folder / "Unrelated" / "app.exe")
            for shared_name in ("Tools", "PortableApps", "Utilities"):
                shared_root = generic_root / shared_name
                shared_root.mkdir(exist_ok=True)
                shared_uninstaller = shared_root / "unins000.exe"
                shared_uninstaller.write_bytes(b"test data; never executed")
                unrelated = shared_root / "Rufus" / "rufus.exe"
                shared_index = PortableInstalledRegistrationIndex.from_inventory(
                    WindowsInstalledInventory([
                        RegistryInstallEntry("Shared uninstaller", "1", "user", "exe",
                                             uninstall_command=f'"{shared_uninstaller}" /quiet'),
                    ])
                )
                assert shared_index.contains(shared_uninstaller)
                assert not shared_index.contains(unrelated)
            for root_path, inside, outside in (
                ("C:\\", "C:\\one\\two\\app.exe", "D:\\one\\app.exe"),
                ("\\\\server\\share\\", "\\\\server\\share\\bin\\app.exe",
                 "\\\\server\\share-extra\\app.exe"),
            ):
                lexical_index = PortableInstalledRegistrationIndex(
                    frozenset(), frozenset({_portable_path_key(root_path)})
                )
                assert lexical_index.contains(inside)
                assert not lexical_index.contains(outside)
    with tempfile.TemporaryDirectory() as paf_tmp:
        paf_root = Path(paf_tmp)
        app_root = paf_root / "ExamplePortable"
        paf_executable = app_root / "App" / "Example" / "Example.exe"
        paf_info = app_root / "App" / "AppInfo" / "appinfo.ini"
        paf_icon = app_root / "App" / "AppInfo" / "appicon.ico"
        paf_executable.parent.mkdir(parents=True)
        paf_info.parent.mkdir(parents=True)
        paf_executable.write_bytes(b"paf-executable")
        paf_icon.write_bytes(b"paf-icon")
        paf_info.write_text(
            (
                "[Format]\n"
                "Type=PortableApps.comFormat\n"
                "Version=3.8\n"
                "[Details]\n"
                "Name=Example Portable\n"
                "AppID=ExamplePortable\n"
                "Publisher=Example Publisher\n"
                "Homepage=https://example.invalid/\n"
                "[Version]\n"
                "PackageVersion=1.2.3.0\n"
                "DisplayVersion=1.2.3\n"
                "[Control]\n"
                "Start=Example\\Example.exe\n"
            ),
            encoding="utf-8",
        )
        paf_metadata = read_portableapps_metadata(paf_info)
        assert paf_metadata is not None
        assert paf_metadata.executable == str(paf_executable)
        paf_result = scan_portable_root(paf_root)
        assert len(paf_result.records) == 1
        assert paf_result.records[0].portable_format == "PortableApps.com"
        assert paf_result.records[0].evidence_score == 120
        assert portable_record_to_item(
            paf_result.records[0]
        ).portable_removal_kind == ""
    with tempfile.TemporaryDirectory() as scan_budget_tmp:
        scan_budget_root = Path(scan_budget_tmp)
        for index in range(250):
            source_dir = scan_budget_root / f"source-{index:03d}"
            source_dir.mkdir()
            (source_dir / "module.py").write_text("pass\n", encoding="utf-8")
            (source_dir / "notes.md").write_text("source\n", encoding="utf-8")
        budget_rufus = scan_budget_root / "Tools" / "rufus-4.15p.exe"
        budget_rufus.parent.mkdir()
        budget_rufus.write_bytes(b"rufus")
        budget_result = scan_portable_root(scan_budget_root)
        assert budget_result.files_checked == 1
        assert not budget_result.truncated
        assert not portable_scan_root_rejection(scan_budget_root / "Program")
        if os.name == "nt":
            system_root = Path(os.environ.get("SystemRoot", r"C:\Windows"))
            assert portable_scan_root_rejection(system_root / "System32")
            program_files = Path(os.environ.get("ProgramFiles", r"C:\Program Files"))
            assert portable_scan_root_rejection(program_files)
        cancelled = threading.Event()
        cancelled.set()
        cancelled_result = scan_portable_root(scan_budget_root, cancelled)
        assert cancelled_result.cancelled
        assert cancelled_result.files_checked == 0
    assert registry_estimated_size_kb("2048") == 2048
    assert registry_estimated_size_kb(0) is None
    assert human_size_from_kb(2048) == "2.0 MB"
    assert pip_show_version("Name: huggingface_hub\nVersion: 1.24.0\n") == "1.24.0"
    assert not pip_show_version("Name: missing-version\n")
    assert (
        pip_list_json_version('[{"name":"HuggingFace-Hub","version":"1.24.0"}]', "huggingface-hub")
        == "1.24.0"
    )
    assert not pip_list_json_version('[{"name":"other","version":"1"}]', "huggingface-hub")
    assert (
        compact_list_summary(["a", "b", "c"], singular="item", plural="items") == "3 items: a, b, c"
    )
    assert compact_list_summary(["a", "b", "c", "d"], singular="item", plural="items") == "4 items"
    assert "pip check" in compact_pip_detail_hint("huggingface_hub")
    npm_script_output = (
        "npm http fetch GET 200 https://registry.npmjs.org/example 22ms\n"
        "npm warn install-scripts example@2.0.0 (node_modules/example) had install scripts blocked\n"
        "changed 1 package in 1s\n"
    )
    assert npm_blocked_install_script_packages(npm_script_output) == ("example",)
    assert compact_npm_output_for_ui(npm_script_output) == "changed 1 package in 1s"
    compact_ui_output = compact_process_output_for_ui(
        "HEAD\n" + ("verbose installer line\n" * 2_000) + "TAIL",
        max_chars=400,
    )
    assert compact_ui_output.startswith("HEAD\n")
    assert "hidden here" in compact_ui_output
    assert compact_ui_output.endswith("TAIL")
    result_item = UpdateItem(
        provider=NpmProvider.key,
        name="Example",
        package_id="example",
        current="1.0.0",
        available="2.0.0",
        source="npm global",
        scope="user",
        requires_admin=False,
    )
    result_entry = {"output": npm_script_output}
    payload_item, payload_entry, payload_output = command_result_event_payload(
        result_item, result_entry
    )
    assert payload_item is result_item and payload_entry is result_entry
    assert payload_output == "changed 1 package in 1s"
    with tempfile.TemporaryDirectory() as npm_tmp:
        npm_root = Path(npm_tmp)
        npm_package = npm_root / "@scope" / "tool"
        npm_package.mkdir(parents=True)
        (npm_package / "cli.js").write_text("console.log('fixture')\n", encoding="utf-8")
        (npm_package / "package.json").write_text(
            json.dumps({"version": "2.0.0", "bin": {"tool": "cli.js"}}),
            encoding="utf-8",
        )
        npm_item = UpdateItem(
            provider=NpmProvider.key,
            name="@scope/tool",
            package_id="@scope/tool",
            current="1.0.0",
            available="2.0.0",
            source="npm global",
            scope="user",
            requires_admin=False,
        )
        npm_integrity, returned_npm_root = npm_post_update_integrity(npm_item, npm_root)
        assert returned_npm_root == npm_root
        assert npm_integrity["verified"]
        assert npm_integrity["version_matches"]
        assert npm_integrity["present_command_targets"] == ["tool"]
        assert not npm_integrity["missing_command_targets"]
        (npm_package / "cli.js").unlink()
        missing_npm_command, _returned_root = npm_post_update_integrity(npm_item, npm_root)
        assert missing_npm_command["missing_command_targets"] == ["tool"]
    missing_suggestions = build_missing_package_suggestions({"microsoft.powershell", "github.cli"})
    assert all(
        suggestion.winget_id not in {"Microsoft.PowerShell", "GitHub.cli"}
        for suggestion in missing_suggestions
    )
    assert any(suggestion.winget_id == "jqlang.jq" for suggestion in missing_suggestions)
    assert not any(
        suggestion.winget_id == "OpenJS.NodeJS.LTS"
        for suggestion in build_missing_package_suggestions(set(), {"node"})
    )
    assert not package_suggestion_catalog_errors()
    assert any(suggestion.winget_id == "OpenAI.Codex" for suggestion in missing_suggestions)
    powershell_suggestion = next(
        suggestion
        for suggestion in PACKAGE_SUGGESTIONS
        if suggestion.winget_id == "Microsoft.PowerShell"
    )
    assert suggestion_install_command(powershell_suggestion).startswith(
        "winget install --id Microsoft.PowerShell --exact --source winget"
    )
    assert "--disable-interactivity" in suggestion_install_command_parts(powershell_suggestion)
    assert "--verbose-logs" in suggestion_install_command_parts(powershell_suggestion)
    suggestion_user_table = """\
Name                    Id                                      Version         Source
--------------------------------------------------------------------------------------
RipGrep MSVC            BurntSushi.ripgrep.MSVC                 15.2.0          winget
"""
    suggestion_machine_table = """\
Name                    Id                                      Version         Source
--------------------------------------------------------------------------------------
Git                     Git.Git                                 2.55.0          winget
"""
    saved_suggestion_run_capture = globals()["run_capture"]
    saved_suggestion_structured_arguments = globals()["winget_structured_output_arguments"]

    def suggestion_inventory_run(
        command: Sequence[str], *, timeout: int, **_kwargs: Any
    ) -> CommandResult:
        del timeout
        command_list = list(command)
        scope = command_list[command_list.index("--scope") + 1]
        output = suggestion_user_table if scope == "user" else suggestion_machine_table
        return CommandResult(0, output, command_list)

    _RECENT_WINGET_INVENTORY.invalidate()
    try:
        globals()["run_capture"] = suggestion_inventory_run
        globals()["winget_structured_output_arguments"] = lambda _command: ()
        suggestion_installed_ids, suggestion_warnings = winget_installed_ids_for_suggestions(
            bypass_recent_cache=True
        )
    finally:
        globals()["run_capture"] = saved_suggestion_run_capture
        globals()["winget_structured_output_arguments"] = (
            saved_suggestion_structured_arguments
        )
        _RECENT_WINGET_INVENTORY.invalidate()
    assert suggestion_installed_ids == {
        "burntsushi.ripgrep.msvc",
        "git.git",
    }
    assert not suggestion_warnings
    assert not any(
        suggestion.winget_id == "BurntSushi.ripgrep.MSVC"
        for suggestion in build_missing_package_suggestions(suggestion_installed_ids)
    )
    suggestion_scan_probe = object.__new__(WinDevPilotApp)
    suggestion_scan_probe._scan_results_current = False
    suggestion_scan_probe._last_scan_completed_at = dt.datetime.now()
    suggestion_scan_probe._scan_current_provider_keys = {WingetProvider.key}
    suggestion_scan_probe._scan_provider_inventory_batches = {
        WingetProvider.key: (
            inventory_only_item(
                provider=WingetProvider.key,
                name="RipGrep MSVC",
                package_id="BurntSushi.ripgrep.MSVC",
                current="15.2.0",
                source="winget",
            ),
        )
    }
    assert WinDevPilotApp._current_winget_ids_for_suggestions(
        suggestion_scan_probe
    ) == {"burntsushi.ripgrep.msvc"}
    suggestion_scan_probe._scan_current_provider_keys.clear()
    assert WinDevPilotApp._current_winget_ids_for_suggestions(suggestion_scan_probe) is None
    npm_chatter, _ = json.JSONDecoder().raw_decode('{"pkg":{"current":"1","latest":"2"}}\nWARN')
    assert npm_chatter["pkg"]["latest"] == "2"
    pip_chatter, _ = json.JSONDecoder().raw_decode('[{"name":"pkg","version":"1"}]\nWARN')
    assert pip_chatter[0]["name"] == "pkg"
    with tempfile.TemporaryDirectory() as temp_settings_dir:
        settings_path = Path(temp_settings_dir) / "settings.json"
        settings_path.write_text(
            json.dumps(
                {
                    "ignored": [123, "Valid.Package"],
                    "window_geometry": "garbage",
                    "window_geometry_dpi": 99999,
                    "provider_duration_hints": {
                        "winget": 3.5,
                        "npm": True,
                        "unknown": 2.0,
                        "scoop": 9999.0,
                    },
                }
            ),
            encoding="utf-8",
        )
        settings_fixture = SettingsStore(settings_path)
        assert settings_fixture.data["schema"] == SETTINGS_SCHEMA_VERSION
        assert settings_fixture.data["ignored"] == ["Valid.Package"]
        assert settings_fixture.data["window_geometry"] == "1280x820"
        assert settings_fixture.data["window_geometry_dpi"] == 0
        assert settings_fixture.data["provider_duration_hints"] == {"winget": 3.5}
        settings_path.write_text(
            json.dumps({"schema": 999, "ignored": ["Future.Package"]}),
            encoding="utf-8",
        )
        unsupported_schema_fixture = SettingsStore(settings_path)
        assert unsupported_schema_fixture.data["ignored"] == []
        assert unsupported_schema_fixture.recovered_corrupt_settings is not None
        assert unsupported_schema_fixture.recovered_corrupt_settings.exists()
        assert (
            "unsupported-schema-999" in unsupported_schema_fixture.recovered_corrupt_settings.name
        )
        settings_path.write_text(json.dumps(["not", "an", "object"]), encoding="utf-8")
        invalid_root_fixture = SettingsStore(settings_path)
        assert invalid_root_fixture.data["ignored"] == []
        assert invalid_root_fixture.recovered_corrupt_settings is not None
        assert "invalid-root" in invalid_root_fixture.recovered_corrupt_settings.name
        settings_path.write_text(json.dumps({"auto_elevate": "false"}), encoding="utf-8")
        invalid_auto_elevate_fixture = SettingsStore(settings_path)
        assert invalid_auto_elevate_fixture.data["auto_elevate"] is True
        assert invalid_auto_elevate_fixture.recovered_corrupt_settings is not None
        assert (
            "invalid-auto-elevate" in invalid_auto_elevate_fixture.recovered_corrupt_settings.name
        )
        settings_path.write_text(
            json.dumps({"providers": {"pip": "false"}}),
            encoding="utf-8",
        )
        invalid_provider_fixture = SettingsStore(settings_path)
        assert invalid_provider_fixture.data["providers"]["pip"] is False
        assert invalid_provider_fixture.recovered_corrupt_settings is not None
        assert "invalid-provider-values" in invalid_provider_fixture.recovered_corrupt_settings.name
        settings_path.write_text("{not json", encoding="utf-8")
        corrupt_fixture = SettingsStore(settings_path)
        assert corrupt_fixture.data["window_geometry"] == "1280x820"
        assert corrupt_fixture.recovered_corrupt_settings is not None
        assert corrupt_fixture.recovered_corrupt_settings.exists()
    assert (
        nonzero_count_summary((("updated", 1), ("failed", 0), ("with warnings", 1)))
        == "1 updated, 1 with warnings"
    )
    item = UpdateItem(
        provider="winget",
        name="Git",
        package_id="Git.Git",
        current="1",
        available="2",
        source="winget",
        scope="machine",
        requires_admin=True,
        instance=2,
    )
    assert SHA256_RE.fullmatch(item.candidate_key)
    assert item.candidate_key != dataclasses.replace(item, available="3").candidate_key
    held_item = dataclasses.replace(item, selected=False, status="Held after failed attempt")
    assert not WinDevPilotApp._item_is_bulk_selectable(held_item)
    assert WinDevPilotApp._item_is_actionable(held_item)
    assert WinDevPilotApp._item_needs_review(held_item)
    ordinary_pip_item = dataclasses.replace(
        item,
        provider=PipProvider.key,
        package_id="sample-pip-package",
        requires_admin=False,
        scope="user",
    )
    assert WinDevPilotApp._item_is_bulk_selectable(ordinary_pip_item)
    assert not WinDevPilotApp._item_is_recommended_selectable(ordinary_pip_item)
    policy_item = dataclasses.replace(item, selected=True, status="Ready")
    held_policy_items = apply_stored_selection_policy(
        [policy_item],
        {"ignored": [], "attempt_holds": {item.candidate_key: {"outcome": "failed"}}},
    )
    assert not held_policy_items[0].selected
    assert held_policy_items[0].status == "Held after failed attempt"
    assert held_policy_items[0].classification == CLASS_MANUAL_REVIEW
    held_scope_item = dataclasses.replace(item, selected=True)
    held_scope_items = apply_stored_selection_policy(
        [held_scope_item],
        {
            "ignored": [],
            "attempt_holds": {
                item.candidate_key: {
                    "outcome": "not-applicable",
                    "returncode_hex": "0x8A150010",
                    "status_hint": "Not applicable - no installer applies to this system",
                }
            },
        },
    )
    assert held_scope_items[0].classification == CLASS_SCOPE_OR_APPLICABILITY
    assert held_scope_items[0].applicability_prediction == PREDICTION_NOT_APPLICABLE
    assert held_scope_items[0].prediction_source == "attempt-hold"
    applicability_record = {
        "classification": CLASS_SCOPE_OR_APPLICABILITY,
        "count": APPLICABILITY_HISTORY_THRESHOLD,
        "last_seen": utc_now_iso(),
        "outcome": "not-applicable",
        "returncode_hex": "0x8A150010",
        "status_hint": "No applicable installer found",
    }
    next_offer = dataclasses.replace(item, available="3", selected=True)
    remembered_items = apply_stored_selection_policy(
        [next_offer],
        {
            "ignored": [],
            "attempt_holds": {},
            "applicability_history": {
                applicability_history_key(item): applicability_record
            },
        },
    )
    assert not remembered_items[0].selected
    assert remembered_items[0].classification == CLASS_SCOPE_OR_APPLICABILITY
    assert remembered_items[0].prediction_source == "installed-instance-applicability-history"
    changed_install = dataclasses.replace(next_offer, current="2", selected=True)
    assert apply_stored_selection_policy(
        [changed_install],
        {
            "ignored": [],
            "attempt_holds": {},
            "applicability_history": {
                applicability_history_key(item): applicability_record
            },
        },
    )[0].selected
    hold_summary = attempt_hold_scan_summary(
        {
            "attempt_holds": {
                item.candidate_key: {
                    "classification": CLASS_MANUAL_REVIEW,
                    "count": 2,
                    "strategy_revision": WINGET_ATTEMPT_STRATEGY_REVISION,
                    "item": item_diagnostic_fields(item),
                    "outcome": "failed",
                    "returncode_hex": "0x00000001",
                    "suppressed": True,
                },
                "0" * 64: {
                    "classification": CLASS_SCOPE_OR_APPLICABILITY,
                    "item": {"name": "Removed", "package_id": "Removed.Package"},
                    "outcome": "not-applicable",
                },
            }
        },
        {item.candidate_key},
    )
    assert hold_summary["total"] == 2
    assert hold_summary["active_count"] == 1
    assert hold_summary["stale_count"] == 1
    assert hold_summary["active"][0]["package_id"] == "Git.Git"
    assert hold_summary["stale"][0]["package_id"] == "Removed.Package"
    with tempfile.TemporaryDirectory() as tmp:
        prune_logger = SessionLogger(Path(tmp))
        prune_settings = {
            "attempt_holds": {
                item.candidate_key: {
                    "classification": CLASS_MANUAL_REVIEW,
                    "item": item_diagnostic_fields(item),
                },
                "1" * 64: {
                    "classification": CLASS_SCOPE_OR_APPLICABILITY,
                    "item": {"package_id": "Removed.Package"},
                },
            },
            "applicability_history": {
                applicability_history_key(item): applicability_record
            },
        }
        removed_holds = prune_stale_attempt_holds(
            prune_settings, {item.candidate_key}, prune_logger
        )
        assert removed_holds == 1
        assert item.candidate_key in prune_settings["attempt_holds"]
        assert "1" * 64 not in prune_settings["attempt_holds"]
        assert prune_logger.flush()
        trace_text = prune_logger.trace_path.read_text(encoding="utf-8")
        assert "attempt_holds_pruned" in trace_text
        assert "Removed.Package" in trace_text
        released_holds = release_attempt_holds(prune_settings, {item.candidate_key}, prune_logger)
        assert released_holds == 1
        assert item.candidate_key not in prune_settings["attempt_holds"]
        assert applicability_history_key(item) not in prune_settings["applicability_history"]
        assert prune_logger.flush()
        trace_text = prune_logger.trace_path.read_text(encoding="utf-8")
        assert "attempt_holds_released" in trace_text
        outcome_settings = SettingsStore(Path(tmp) / "outcome-settings.json")
        outcome_probe = object.__new__(WinDevPilotApp)
        outcome_probe.items = {item.key: item}
        outcome_probe._scan_view_items = {False: outcome_probe.items, True: {}}
        outcome_probe.settings = outcome_settings
        outcome_probe.logger = prune_logger
        outcome_probe.active_update_id = "self-test-update"
        outcome_probe.active_attempt_kind = "update"
        outcome_probe._append_log = lambda *_args, **_kwargs: None
        failed_outcome = {
            "key": item.key,
            "success": False,
            "outcome": "not-applicable",
            "returncode_hex": "0x8A150010",
            "status_hint": "No applicable installer found",
            "finished_at": "2026-07-20T12:00:00+00:00",
        }
        retryable_outcome = {
            **failed_outcome,
            "outcome": "failed",
            "returncode_hex": "0x8A150086",
            "status_hint": "Another installation is in progress; retry after it finishes",
        }
        assert retryable_failure_candidate_keys(
            [retryable_outcome], outcome_probe.items
        ) == {item.candidate_key}
        assert not retryable_failure_candidate_keys([failed_outcome], outcome_probe.items)
        retry_context = retryable_failure_context(
            {
                "attempt_holds": {
                    item.candidate_key: {
                        "item": item_diagnostic_fields(item),
                        "status_hint": retryable_outcome["status_hint"],
                    }
                }
            },
            {item.candidate_key},
        )
        assert item.name in retry_context
        assert "Another installation is in progress" in retry_context
        WinDevPilotApp._remember_attempt_outcomes(outcome_probe, [failed_outcome])
        WinDevPilotApp._remember_attempt_outcomes(
            outcome_probe,
            [{**failed_outcome, "finished_at": "2026-07-20T13:00:00+00:00"}],
        )
        remembered_history = outcome_settings.data["applicability_history"][
            applicability_history_key(item)
        ]
        assert remembered_history["count"] == 2
        verification_conflict_outcome = {
            "key": item.key,
            "success": False,
            "outcome": "verification-conflict",
            "returncode_hex": "0x00000000",
            "classification": CLASS_VERIFICATION_CONFLICT,
            "status_hint": (
                "The package manager reported success, but a fresh read-only scan still "
                "offered this same exact update."
            ),
            "finished_at": "2026-07-20T13:30:00+00:00",
        }
        WinDevPilotApp._remember_attempt_outcomes(
            outcome_probe, [verification_conflict_outcome]
        )
        conflict_hold = outcome_settings.data["attempt_holds"][item.candidate_key]
        assert conflict_hold["classification"] == CLASS_VERIFICATION_CONFLICT
        held_item = apply_stored_selection_policy(
            [dataclasses.replace(item, selected=True)], outcome_settings.data
        )[0]
        assert not held_item.selected
        assert held_item.classification == CLASS_VERIFICATION_CONFLICT
        assert held_item.applicability_prediction == PREDICTION_UNKNOWN
        assert "reported success" in " ".join(held_item.prediction_reasons)
        WinDevPilotApp._remember_attempt_outcomes(
            outcome_probe,
            [
                {
                    "key": item.key,
                    "success": True,
                    "outcome": "updated",
                    "finished_at": "2026-07-20T14:00:00+00:00",
                }
            ],
        )
        assert not outcome_settings.data["applicability_history"]
        assert not outcome_settings.data["attempt_holds"]
        assert not outcome_settings.data["package_history"]
        outcome_settings.data["package_history"] = remember_package_history_event(
            {},
            provider=item.provider,
            package_id=item.package_id,
            name=item.name,
            action="update",
            observed_at="2026-07-20T14:00:00+00:00",
            version=item.available,
            scope=item.scope,
            source=item.source,
        )
        remembered_package = package_history_for_item(outcome_settings.data, item)
        assert remembered_package["serviced_at"] == "2026-07-20T14:00:00+00:00"
        assert remembered_package["serviced_version"] == item.available
        reboot_success = {
            "key": item.key,
            "success": True,
            "outcome": "updated",
            "needs_reboot": True,
            "returncode_hex": "0x00000BC2",
            "finished_at": "2026-07-20T14:05:00+00:00",
        }
        with patch(f"{__name__}.system_boot_id", return_value=41):
            WinDevPilotApp._remember_attempt_outcomes(outcome_probe, [reboot_success])
        restart_marker = outcome_settings.data["restart_pending"][
            item.verification_identity_key
        ]
        assert restart_marker["boot_id"] == 41
        with patch(f"{__name__}.system_boot_id", return_value=41):
            pre_restart_item = apply_stored_selection_policy(
                [dataclasses.replace(item, selected=True)], outcome_settings.data
            )[0]
        assert not pre_restart_item.selected
        assert pre_restart_item.status == "Restart required to finish previous attempt"
        assert pre_restart_item.prediction_source == "restart-pending-marker"
        for shift in (-7 * 86400, 0, 7 * 86400):
            with patch.object(time, "time", return_value=restart_marker["attempt_epoch"] + shift):
                assert not restarted_after_pending_marker(restart_marker, boot_id=41)
                assert restarted_after_pending_marker(restart_marker, boot_id=42)
                assert not restarted_after_pending_marker(restart_marker, boot_id=40)
        for invalid_boot in (None, "41", True, -1, 2**32, float("nan")):
            invalid_marker = {**restart_marker, "boot_id": invalid_boot}
            assert not restarted_after_pending_marker(invalid_marker, boot_id=42)
            with patch(f"{__name__}.system_boot_id", return_value=invalid_boot):
                assert not restarted_after_pending_marker(restart_marker)
        legacy_marker = {key: value for key, value in restart_marker.items() if key != "boot_id"}
        legacy_marker.update(schema=1, boot_epoch=1.0)
        legacy_settings = {"restart_pending": {item.verification_identity_key: legacy_marker}}
        migrated = reconcile_restart_pending_markers(
            legacy_settings, [item], {item.provider}, boot_id=41,
        )
        assert migrated["changed"] and not migrated["held_candidate_keys"]
        assert "boot_id" not in legacy_marker  # Migration must not mutate its input alias.
        assert legacy_settings["restart_pending"][item.verification_identity_key]["boot_id"] == 41
        assert not reconcile_restart_pending_markers(
            legacy_settings, [item], {item.provider}, boot_id=41,
        )["changed"]
        assert reconcile_restart_pending_markers(
            legacy_settings, [], {item.provider}, boot_id=42,
        )["resolved_identity_keys"] == [item.verification_identity_key]
        post_restart_item = dataclasses.replace(item, available=f"{item.available}.0")
        post_restart = reconcile_restart_pending_markers(
            outcome_settings.data,
            [post_restart_item],
            {item.provider},
            boot_id=42,
        )
        assert post_restart["changed"]
        assert post_restart["held_candidate_keys"] == [
            post_restart_item.candidate_key
        ]
        assert not outcome_settings.data["restart_pending"]
        assert (
            outcome_settings.data["attempt_holds"][post_restart_item.candidate_key][
                "classification"
            ]
            == CLASS_VERIFICATION_CONFLICT
        )
        resolved_restart_settings = {
            "restart_pending": {
                item.verification_identity_key: dict(restart_marker)
            },
            "attempt_holds": {},
            "package_history": {},
        }
        resolved_restart = reconcile_restart_pending_markers(
            resolved_restart_settings,
            [],
            {item.provider},
            boot_id=42,
        )
        assert resolved_restart["resolved_identity_keys"] == [
            item.verification_identity_key
        ]
        resolved_history = package_history_for_item(
            resolved_restart_settings,
            item,
        )
        assert resolved_history["serviced_at"] == reboot_success["finished_at"]
        assert resolved_history["serviced_version"] == item.available

        class FailingSettings:
            def __init__(self) -> None:
                self.data = {
                    "attempt_holds": {},
                    "restart_pending": {},
                    "applicability_history": {},
                }

            def save(self) -> None:
                raise OSError("self-test write failure")

        rollback_probe = object.__new__(WinDevPilotApp)
        rollback_probe._scan_view_items = {False: {item.key: item}, True: {}}
        rollback_probe.settings = FailingSettings()
        rollback_probe.logger = prune_logger
        rollback_probe.active_update_id = "rollback-self-test"
        rollback_probe._append_log = lambda *_args, **_kwargs: None
        WinDevPilotApp._remember_attempt_outcomes(
            rollback_probe,
            [failed_outcome],
        )
        assert rollback_probe.settings.data == {
            "attempt_holds": {},
            "restart_pending": {},
            "applicability_history": {},
        }

        suggested_installed = inventory_only_item(
            provider=WingetProvider.key,
            name="Suggested fixture",
            package_id="Example.Suggested",
            current="4.2.0",
            source="winget",
            scope="machine",
        )
        suggested_probe = object.__new__(WinDevPilotApp)
        suggested_probe._pending_suggested_install_history = {
            "winget\0example.suggested": {
                "provider": WingetProvider.key,
                "package_id": "Example.Suggested",
                "name": "Suggested fixture",
                "observed_at": "2026-08-30T12:00:00+00:00",
            }
        }
        suggested_probe._scan_current_provider_keys = {WingetProvider.key}
        suggested_probe.settings = SettingsStore(
            Path(tmp) / "suggested-history-settings.json"
        )
        suggested_probe.logger = prune_logger
        suggested_probe.active_update_id = "suggested-self-test"
        suggested_probe._append_log = lambda *_args, **_kwargs: None
        WinDevPilotApp._confirm_pending_suggested_install_history(
            suggested_probe,
            [suggested_installed],
        )
        assert not suggested_probe._pending_suggested_install_history
        suggested_history = package_history_for_item(
            suggested_probe.settings.data,
            suggested_installed,
        )
        assert suggested_history["installed_at"] == "2026-08-30T12:00:00+00:00"
        assert suggested_history["installed_version"] == "4.2.0"

        class FailingHistorySettings:
            def __init__(self) -> None:
                self.data = {"package_history": {}}

            def save(self) -> None:
                raise OSError("self-test write failure")

        suggested_probe.settings = FailingHistorySettings()
        suggested_probe._pending_suggested_install_history = {
            "winget\0example.suggested": {
                "provider": WingetProvider.key,
                "package_id": "Example.Suggested",
                "name": "Suggested fixture",
                "observed_at": "2026-08-30T12:00:00+00:00",
            }
        }
        WinDevPilotApp._confirm_pending_suggested_install_history(
            suggested_probe,
            [suggested_installed],
        )
        assert suggested_probe._pending_suggested_install_history
        assert not suggested_probe.settings.data["package_history"]
        assert prune_logger.close()
    exact_list_rows = winget_exact_list_rows(
        """
Name       Id       Version  Source
-----------------------------------
Git        Git.Git  2.55.0   winget
"""
    )
    assert exact_list_rows[0]["Id"] == "Git.Git"
    assert normalized_registry_install_date("20260716") == "2026-07-16"
    assert normalized_registry_install_date("2026-07-16") == "2026-07-16"
    assert normalized_registry_install_date("20260231") == ""
    assert normalize_wall_clock_timestamp("2026-09-04") == (
        "2026-09-04",
        "date",
    )
    assert normalize_wall_clock_timestamp("2026-09-04T12:13:14+02:30") == (
        "2026-09-04T12:13:14+02:30",
        "second",
    )
    assert normalize_wall_clock_timestamp("2026-09-04T12:13:14.125Z") == (
        "2026-09-04T12:13:14.125000+00:00",
        "fractional-3",
    )
    assert normalize_wall_clock_timestamp("2026-09-04T12:13:14.125678-04:00") == (
        "2026-09-04T12:13:14.125678-04:00",
        "fractional-6",
    )
    assert ".13 " in local_observation_time(
        "2026-09-04T12:13:14.125000+00:00", "fractional-3"
    )
    assert ":14.00 " in local_observation_time("2026-09-04T12:13:14+00:00")
    assert datetime_display_timestamp(
        dt.datetime(2026, 9, 4, 12, 13, 14, 994_999, tzinfo=dt.UTC)
    ) == "2026-09-04T12:13:14.99+00:00"
    assert datetime_display_timestamp(
        dt.datetime(2026, 9, 4, 12, 13, 14, 995_000, tzinfo=dt.UTC)
    ) == "2026-09-04T12:13:15.00+00:00"
    assert datetime_storage_timestamp(
        dt.datetime(2026, 9, 4, 12, 13, 14, 995_000, tzinfo=dt.UTC)
    ) == "2026-09-04T12:13:14.995000+00:00"
    assert _package_history_timestamp("2026-09-04T12:00:00+02:00") < (
        _package_history_timestamp("2026-09-04T10:30:00+00:00")
    )
    assert wall_clock_order_key("2026-09-04T12:00:00+02:00") < (
        wall_clock_order_key("2026-09-04T10:30:00+00:00")
    )
    store_time_result = CommandResult(
        0,
        json.dumps(
            {
                "full_name": "Example.Store_1.0.0.0_x64__publisher",
                "installed_timestamp": "2026-09-04T12:13:14.987654Z",
            }
        ),
        ["powershell.exe"],
    )
    with (
        patch.object(shutil, "which", return_value=r"C:\Windows\powershell.exe"),
        patch(f"{__name__}.run_capture", return_value=store_time_result) as store_time_probe,
    ):
        store_times, store_time_error = windows_app_package_installed_dates()
    assert not store_time_error
    assert store_times["example.store_1.0.0.0_x64__publisher"] == (
        "2026-09-04T12:13:14.987654+00:00",
        "fractional-6",
    )
    assert "installed_timestamp" in store_time_probe.call_args.args[0][-1]
    assert "ffffffZ" in store_time_probe.call_args.args[0][-1]
    if os.name == "nt":
        # Keep the real PowerShell projection/JSON parser, replace only WinRT
        # enumeration. No package API, manifest file access or installation here.
        package_fixture = r"""
$ErrorActionPreference='Stop';
function Test-Path { param([string]$LiteralPath) return $true }
function Get-Content {
    [CmdletBinding()] param([string]$LiteralPath,[switch]$Raw)
    return '<Package><Applications><Application Id="App"><VisualElements /></Application><Application Id="Helper"><VisualElements AppListEntry="none" /></Application><Application Id="Background" /></Applications></Package>'
}
function New-PackageFixture($name,$date,$framework=$false) {
    [pscustomobject]@{
        Id=[pscustomobject]@{Name=$name;FullName=($name+'_1.0.0.0_x64__publisher');
            FamilyName=($name+'__publisher');Version=[version]'1.0.0.0';Architecture='X64'}
        InstalledDate=$date;IsFramework=$framework;IsResourcePackage=$false
        SignatureKind='Store';InstalledLocation=[pscustomobject]@{Path='C:\Fixture'};Logo=$null
        DisplayName=$name;PublisherDisplayName='Fixture';Description=''
    }
}
$known=[DateTimeOffset]::Parse('2026-09-04T12:13:14.987654Z');
$absent=New-PackageFixture 'Example.Absent' $null;
$absent.PSObject.Properties.Remove('InstalledDate');
$fixturePackages=@($null,[pscustomobject]@{Id=$null},
    (New-PackageFixture 'Example.Before' $known),
    (New-PackageFixture 'Example.Null' $null),$absent,
    (New-PackageFixture 'Example.FrameworkNull' $null $true),
    (New-PackageFixture 'Example.FrameworkKnown' $known $true),
    (New-PackageFixture 'Example.After' $known));
"""
        actual_capture = run_capture

        def package_fixture_capture(command: Sequence[str], **kwargs: Any) -> CommandResult:
            projection = list(command)
            _, marker, body = projection[-1].partition("$rows=@(")
            assert marker and body.count("$pm.FindPackagesForUser($sid)") == 1
            projection[-1] = package_fixture + marker + body.replace(
                "$pm.FindPackagesForUser($sid)", "$fixturePackages",
            )
            return actual_capture(projection, **kwargs)

        with patch(f"{__name__}.run_capture", side_effect=package_fixture_capture):
            fixture_records, fixture_error = microsoft_store_package_inventory()
            fixture_dates, fixture_date_error = windows_app_package_installed_dates()
        assert not fixture_error, fixture_error
        assert not fixture_date_error, fixture_date_error
        assert len(fixture_records) == 6
        for record in fixture_records:
            if not record.get("date_only"):
                assert record["launch_ids"] == ["App"]
                assert record["launchable"] is True
        assert len(fixture_dates) == 3
        assert windows_package_dates_from_records(fixture_records) == fixture_dates
        for record in fixture_records:
            if any(name in record["full_name"] for name in (".Null_", ".Absent_", "FrameworkNull_")):
                assert record["installed_timestamp"] == ""
            else:
                assert record["installed_timestamp"] == "2026-09-04T12:13:14.987654Z"
        fixture_provider = MicrosoftStoreProvider()
        with patch(f"{__name__}.microsoft_store_package_inventory",
                   return_value=(fixture_records, "")):
            fixture_items = fixture_provider._native_inventory()
        assert len(fixture_items) == 4  # Date-only framework records stay out of Store rows.
        assert not fixture_provider.warnings
        for fixture_item in fixture_items:
            if fixture_item.name in {"Example.Null", "Example.Absent"}:
                assert not fixture_item.installed_timestamp and not fixture_item.installed_date
        with patch(f"{__name__}.run_capture", return_value=CommandResult(
            1, "Package enumeration failed", ["powershell.exe"],
        )):
            assert microsoft_store_package_inventory() == ([], "Package enumeration failed")
            assert windows_app_package_installed_dates() == ({}, "Package enumeration failed")
    date_item = UpdateItem(
        provider="npm", name="Codex (CLI)", package_id="@openai/codex",
        current="0.153.0", available="0.153.0", scope="user", source="npm global",
    )
    service_time = dt.datetime(2026, 9, 2, 23, 35, 48, 123456).astimezone()
    service_history = remember_package_history_event(
        {}, provider=date_item.provider, package_id=date_item.package_id,
        name=date_item.name, action="update", observed_at=service_time.isoformat(),
        version=date_item.current, scope=date_item.scope, source=date_item.source,
    )
    date_settings = {"package_history": service_history}
    expected_date = InstalledServiceDate(
        "2026-09-02",
        "Updated by WinDevPilot (verified)",
        timestamp=service_time.isoformat(timespec="microseconds"),
        timestamp_precision="fractional-6",
        history_action="update",
    )
    with (
        patch.object(Path, "stat", side_effect=AssertionError("date display accessed disk")),
        patch.object(Path, "open", side_effect=AssertionError("date display opened a file")),
        patch(f"{__name__}.run_capture", side_effect=AssertionError("date display ran a command")),
    ):
        assert installed_service_date_evidence(date_item, date_settings) == expected_date
    assert not date_item.installed_date  # Provider evidence stays unchanged.
    assert not installed_service_date_evidence(date_item, {}).date
    for native_day, approximate, use_history in (
        ("2026-09-01", False, True), ("2026-09-02", False, True),
        ("2026-09-03", False, False), ("2026-09-03", True, True),
        ("2026-09-02", True, True), ("not-a-date", False, True),
    ):
        native_item = dataclasses.replace(
            date_item, installed_date=native_day, installed_date_is_estimate=approximate,
            installed_date_source="Windows uninstall registration last changed",
        )
        evidence = installed_service_date_evidence(native_item, date_settings)
        assert bool(evidence.history_action) == use_history, (native_day, approximate)
        assert evidence.date == (expected_date.date if use_history else native_day)
    for changed_field, value in (
        ("provider", "winget"), ("package_id", "Other.Package"),
        ("scope", "machine"), ("source", "different-prefix"),
    ):
        assert not installed_service_date_evidence(
            dataclasses.replace(date_item, **{changed_field: value}), date_settings
        ).date
    assert installed_service_date_evidence(
        dataclasses.replace(date_item, name="New display label", instance=2), date_settings
    ) == expected_date
    history_key = next(iter(service_history))
    generic_key = package_history_key_from_fields(date_item.provider, date_item.package_id)
    assert not installed_service_date_evidence(
        date_item, {"package_history": {generic_key: service_history[history_key]}}
    ).date
    for bad_time in (None, [], "invalid", "2026-09-02", "2026-09-02T23:35:48"):
        invalid_history = {
            history_key: {**service_history[history_key], "last_serviced_by_windevpilot_at": bad_time}
        }
        assert not installed_service_date_evidence(
            date_item, {"package_history": invalid_history}
        ).date
    for invalid_action in ("failed", "unverified", "uninstall", None, []):
        assert not installed_service_date_evidence(date_item, {"package_history": {
            history_key: {**service_history[history_key], "last_action": invalid_action}
        }}).date
    utc_history = {history_key: {
        **service_history[history_key],
        "last_serviced_by_windevpilot_at": service_time.astimezone(dt.UTC).isoformat(),
    }}
    utc_evidence = installed_service_date_evidence(date_item, {"package_history": utc_history})
    assert utc_evidence.detail_text == expected_date.detail_text
    assert utc_evidence.history_action == expected_date.history_action
    installed_history = remember_package_history_event(
        {}, provider=date_item.provider, package_id=date_item.package_id,
        name=date_item.name, action="install",
        observed_at=(service_time - dt.timedelta(days=1)).isoformat(),
        version="0.152.1", scope=date_item.scope, source=date_item.source,
    )
    assert installed_service_date_evidence(date_item, {"package_history": installed_history}) == (
        InstalledServiceDate(
            "2026-09-01",
            "Installed by WinDevPilot (verified)",
            timestamp=(service_time - dt.timedelta(days=1)).isoformat(
                timespec="microseconds"
            ),
            timestamp_precision="fractional-6",
            history_action="install",
        )
    )
    serviced_history = remember_package_history_event(
        installed_history, provider=date_item.provider, package_id=date_item.package_id,
        name=date_item.name, action="update", observed_at=service_time.isoformat(),
        version=date_item.current, scope=date_item.scope, source=date_item.source,
    )
    assert installed_service_date_evidence(date_item, {"package_history": serviced_history}) == expected_date
    assert serviced_history[history_key]["installed_by_windevpilot_at"] == (
        installed_history[history_key]["installed_by_windevpilot_at"]
    )
    same_time_history = {history_key: {
        **serviced_history[history_key], "installed_by_windevpilot_at": service_time.isoformat(),
    }}
    assert installed_service_date_evidence(date_item, {"package_history": same_time_history}) == expected_date
    legacy_native = dataclasses.replace(
        date_item, installed_date="2026-09-01", installed_date_is_estimate=True,
        installed_date_source="Windows uninstall registration last changed (approximate)",
    )
    assert installed_service_date_evidence(legacy_native, {}).source == (
        "Windows installed-app registration last changed (approximate)"
    )
    absent_time = service_time + dt.timedelta(days=1)
    returned_time = absent_time + dt.timedelta(days=1)
    absent_history = remember_package_history_absences(
        serviced_history, [], {"npm"}, absent_time.isoformat()
    )
    assert absent_history[history_key] == {
        **serviced_history[history_key], "inventory_absent_at": absent_time.isoformat()
    }
    assert "inventory_absent_at" not in serviced_history[history_key]
    assert not installed_service_date_evidence(date_item, {"package_history": absent_history}).date
    assert installed_service_date_evidence(legacy_native, {"package_history": absent_history}) == (
        installed_service_date_evidence(legacy_native, {})
    )
    for present_items, fresh_keys, observed_at in (
        ([date_item], {"npm"}, absent_time.isoformat()),
        ([dataclasses.replace(date_item, scope="unknown", source="")], {"npm"}, absent_time.isoformat()),
        ([dataclasses.replace(date_item, scope="machine")], {"npm"}, absent_time.isoformat()),
        ([], set(), absent_time.isoformat()),  # Reused/partial/unavailable coverage.
        ([], {"winget"}, absent_time.isoformat()),
        ([], {"npm"}, service_time.isoformat()),
        ([], {"npm"}, "invalid"),
        ([], {"npm"}, "2026-09-03T12:00:00"),
    ):
        assert remember_package_history_absences(
            serviced_history, present_items, fresh_keys, observed_at
        ) == serviced_history
    assert remember_package_history_absences(
        absent_history, [], {"npm"}, returned_time.isoformat()
    ) == absent_history  # Continued absence does not rewrite settings.
    assert remember_package_history_absences(
        absent_history, [date_item], {"npm"}, returned_time.isoformat()
    ) == absent_history  # Reappearance alone cannot restore the old date claim.
    for unscoped in ("", "unknown"):
        unscoped_history = remember_package_history_event(
            {}, provider="npm", package_id=date_item.package_id, name=date_item.name,
            action="install", observed_at=service_time.isoformat(), scope=unscoped,
        )
        assert remember_package_history_absences(
            unscoped_history, [], {"npm"}, absent_time.isoformat()
        ) == unscoped_history
    legacy_history = {generic_key: serviced_history[history_key]}
    assert remember_package_history_absences(
        legacy_history, [], {"npm"}, absent_time.isoformat()
    ) == legacy_history
    assert remember_package_history_absences(
        serviced_history, [dataclasses.replace(date_item, provider="winget")],
        {"npm"}, absent_time.isoformat(),
    ) == absent_history  # Another provider cannot prove this installation present.
    for invalid_absence in (None, [], "invalid", "2026-09-03T12:00:00"):
        assert not installed_service_date_evidence(date_item, {"package_history": {
            history_key: {**serviced_history[history_key], "inventory_absent_at": invalid_absence}
        }}).date
    assert package_history_action_is_current({
        "inventory_absent_at": absent_time.astimezone(dt.UTC).isoformat(),
        "last_serviced_by_windevpilot_at": returned_time.isoformat(),
    }, "last_serviced_by_windevpilot_at")
    for action in ("install", "update"):
        fresh_history = remember_package_history_event(
            absent_history, provider=date_item.provider, package_id=date_item.package_id,
            name=date_item.name, action=action, observed_at=returned_time.isoformat(),
            version="0.154.0", scope=date_item.scope, source=date_item.source,
        )
        assert fresh_history[history_key]["inventory_absent_at"] == absent_time.isoformat()
        assert fresh_history[history_key]["installed_by_windevpilot_at"] == (
            installed_history[history_key]["installed_by_windevpilot_at"]
        )
        fresh_settings = {"package_history": fresh_history}
        assert installed_service_date_evidence(date_item, fresh_settings).history_action == action
        assert installed_service_date_evidence(date_item, fresh_settings).date == "2026-09-04"
        fresh_details_history = package_history_for_item(fresh_settings, date_item)
        assert not fresh_details_history["installed_current"]
        assert fresh_details_history["serviced_current"]
        second_absence = remember_package_history_absences(
            fresh_history, [], {"npm"}, (returned_time + dt.timedelta(days=1)).isoformat()
        )
        assert second_absence[history_key]["inventory_absent_at"] != absent_time.isoformat()
        assert not installed_service_date_evidence(date_item, {"package_history": second_absence}).date
    with tempfile.TemporaryDirectory(prefix="wdp-service-date-test-") as date_temp:
        history_path = Path(date_temp) / "settings.json"
        date_store = SettingsStore(history_path)
        date_store.data["package_history"] = service_history
        date_store.save()
        reloaded_date_store = SettingsStore(history_path)
        assert installed_service_date_evidence(date_item, reloaded_date_store.data) == expected_date
        date_probe = object.__new__(WinDevPilotApp)
        date_probe.settings = reloaded_date_store
        date_probe.providers = {"npm": NpmProvider()}
        date_probe.process_is_admin = False
        date_probe._provisional_inventory_keys = {date_item.key}
        assert date_probe._item_row_values(date_item)[5] == "2026-09-02"
        assert date_probe._item_row_values(date_item)[3] == "Checking…"
        date_probe._provisional_inventory_keys.clear()
        date_details = date_probe.item_details_text(date_item)
        assert f"Installed / last serviced: {expected_date.detail_text}" in date_details
        assert "Date/time evidence: Updated by WinDevPilot (verified)" in date_details
        assert "Recorded precision: microsecond" in date_details
        assert "Installed through WinDevPilot:" not in date_details
        undated = dataclasses.replace(date_item, package_id="Undated.App")
        older = dataclasses.replace(undated, package_id="Older.App", installed_date="2026-09-01")
        for newest, expected in ((True, [date_item, older, undated]), (False, [older, date_item, undated])):
            assert sorted([undated, date_item, older], key=lambda value: (
                date_probe._installed_date_sort_value(value, newest)
            )) == expected
        same_day_early = dataclasses.replace(
            older,
            package_id="Same.Day.Early",
            installed_date="2026-09-02",
            installed_timestamp="2026-09-02T08:00:00.100000-04:00",
            installed_timestamp_precision="fractional-6",
        )
        same_day_late = dataclasses.replace(
            older,
            package_id="Same.Day.Late",
            installed_date="2026-09-02",
            installed_timestamp="2026-09-02T17:00:00.900000-04:00",
            installed_timestamp_precision="fractional-6",
        )
        assert sorted(
            [same_day_late, same_day_early],
            key=lambda value: date_probe._installed_date_sort_value(value, False),
        ) == [same_day_early, same_day_late]
        assert sorted(
            [same_day_early, same_day_late],
            key=lambda value: date_probe._installed_date_sort_value(value, True),
        ) == [same_day_late, same_day_early]
        assert date_probe._sort_value(date_item, "installed_date") == "2026-09-02"
        date_probe.items = {date_item.key: date_item}
        date_probe._icon_scroll_quiet_until = 0
        date_probe._hover_row = date_item.key
        date_probe._tooltip_key = ""
        date_probe._tooltip_window = None
        date_probe.tree = Mock()
        date_probe.tree.identify_region.return_value = "cell"
        date_probe.tree.identify_row.return_value = date_item.key
        date_probe.tree.winfo_rootx.return_value = 0
        date_probe.tree.winfo_rooty.return_value = 0
        date_probe._tree_display_column_name = lambda _column: "installed_date"
        date_probe.visuals = type("DateVisualFixture", (), {"px": lambda _self, value: value})()
        date_probe._schedule_tooltip = Mock()
        date_probe._tree_motion(type("DateMotionFixture", (), {
            "x": 10, "y": 10, "x_root": 10, "y_root": 10
        })())
        tooltip = date_probe._schedule_tooltip.call_args.args[1]
        assert "Updated by WinDevPilot (verified)" in tooltip
        assert "No trustworthy" not in tooltip
        assert "not necessarily the first installation" in tooltip
        date_probe.logger = Mock()
        date_probe._append_log = Mock()
        date_probe.settings.data["package_history"] = serviced_history
        with patch.object(date_probe.settings, "save", side_effect=OSError("test failure")):
            date_probe._remember_confirmed_history_absences([], {"npm"}, absent_time.isoformat())
        assert date_probe.settings.data["package_history"] == serviced_history
        assert date_probe._append_log.call_count == 1
        date_probe.logger.event.assert_not_called()
        date_probe._remember_confirmed_history_absences([], {"npm"}, absent_time.isoformat())
        date_probe.settings = SettingsStore(history_path)
        assert date_probe.settings.data["package_history"] == absent_history
        assert not date_probe._item_row_values(date_item)[5]
        historical_details = date_probe.item_details_text(date_item)
        assert "Earlier actions are historical only" in historical_details
        assert "Installed through WinDevPilot:" not in historical_details
        assert "WinDevPilot previously updated this package ID:" in historical_details
        with patch.object(date_probe.settings, "save") as history_save:
            date_probe._remember_confirmed_history_absences([], set(), returned_time.isoformat())
            date_probe._remember_confirmed_history_absences([], {"npm"}, returned_time.isoformat())
            date_probe._remember_confirmed_history_absences([date_item], {"npm"}, returned_time.isoformat())
        history_save.assert_not_called()
        date_probe.settings.data["package_history"] = fresh_history
        assert "Last updated by WinDevPilot:" in date_probe.item_details_text(date_item)
        date_probe.settings.data["package_history"] = remember_package_history_event(
            absent_history, provider=date_item.provider, package_id=date_item.package_id,
            name=date_item.name, action="install", observed_at=returned_time.isoformat(),
            scope=date_item.scope, source=date_item.source,
        )
        reinstalled_details = date_probe.item_details_text(date_item)
        assert "Last installed by WinDevPilot:" in reinstalled_details
        assert "Last updated by WinDevPilot:" not in reinstalled_details
        assert "Installed / last serviced: " in reinstalled_details
        assert local_observation_time(returned_time.isoformat()) in reinstalled_details
    with tempfile.TemporaryDirectory() as tmp:
        date_root = Path(tmp) / "Sample App"
        date_root.mkdir()
        date_icon = date_root / "sample.exe"
        date_icon.write_bytes(b"fixture")
        inferred_date, inferred_timestamp, inferred_paths = corroborated_local_service_date(
            (date_root, date_icon)
        )
        assert inferred_date == dt.date.today().isoformat()
        assert normalize_wall_clock_timestamp(inferred_timestamp)[1] == "fractional-6"
        assert len(inferred_paths) == 2
        sleuth_item = dataclasses.replace(
            item,
            scope="user",
            installed_location=str(date_root),
            icon_source=str(date_icon),
        )
        assert local_date_sleuth_paths(sleuth_item) == (date_root, date_icon)
        artwork_only_item = dataclasses.replace(
            sleuth_item, package_id="Anthropic.Claude", name="Claude (Desktop app)",
            installed_location="", icon_source=str(date_icon), installed_date="",
        )
        with patch.object(Path, "resolve", side_effect=AssertionError("artwork-only date probe touched disk")):
            assert not local_date_sleuth_paths(artwork_only_item)
        brand_root = Path(tmp) / "Shared branding"
        brand_root.mkdir()
        brand_icon = brand_root / "sample.png"
        brand_icon.write_bytes(b"image fixture")
        assert local_date_sleuth_paths(dataclasses.replace(
            sleuth_item, installed_location=str(brand_root), icon_source=str(brand_icon)
        )) == (brand_root,)
        outside_executable = Path(tmp) / "cli.exe"
        outside_executable.write_bytes(b"CLI fixture")
        located_item = dataclasses.replace(
            sleuth_item, name="Sample", package_id="Example.Sample", installed_date="",
            icon_source="",
        )
        assert local_date_sleuth_paths(dataclasses.replace(
            located_item, icon_source=str(outside_executable)
        )) == (date_root, date_icon)
        assert local_date_sleuth_paths(dataclasses.replace(
            located_item, icon_source=str(brand_icon)
        )) == (date_root, date_icon)
        linked_root = Path(tmp) / "Linked App"
        linked_root.mkdir()
        linked_payload = linked_root / "linked.exe"
        try:
            linked_payload.symlink_to(outside_executable)
        except OSError as exc:
            if getattr(exc, "winerror", None) != 1314:
                raise
        else:
            assert local_date_sleuth_paths(dataclasses.replace(
                located_item, name="Linked", installed_location=str(linked_root)
            )) == (linked_root,)
        native_date_item = dataclasses.replace(
            artwork_only_item, package_id=r"MSIX\Example.Native_1.0.0.0_x64__publisher",
        )
        idle_probe = object.__new__(WinDevPilotApp)
        idle_probe._closing = False
        idle_probe._date_sleuth_active = False
        idle_probe._date_sleuth_after_id = None
        idle_probe._date_sleuth_completed_signature = ""
        idle_probe._date_sleuth_generation = 1
        idle_probe._date_sleuth_can_start = lambda: True
        idle_probe._scan_view_items = {True: {
            entry.key: entry for entry in (artwork_only_item, located_item, native_date_item)
        }}
        idle_probe._item_icon_source_cache = {}
        date_signature = idle_probe._date_sleuth_signature()
        idle_probe._item_icon_source_cache = {
            entry.key: outside_executable for entry in idle_probe._scan_view_items[True].values()
        }
        assert idle_probe._date_sleuth_signature() == date_signature
        idle_probe.events = queue.Queue()
        with (
            patch.object(threading, "Thread") as date_thread,
            patch(f"{__name__}.windows_app_package_installed_dates", return_value=(
                {
                    native_date_item.package_id.split("\\", 1)[1].casefold(): (
                        "2026-08-20T15:16:17.123456+00:00",
                        "fractional-6",
                    )
                },
                "",
            )),
            patch(f"{__name__}.local_date_sleuth_paths", wraps=local_date_sleuth_paths) as date_paths,
        ):
            idle_probe._run_idle_date_sleuth()
            date_thread.call_args.kwargs["target"]()  # Exercise worker without Tk or native queries.
            assert date_paths.call_count == 1
            assert date_paths.call_args.args[0].icon_source == ""
        event_kind, date_payload = idle_probe.events.get_nowait()
        assert event_kind == "idle_dates_done" and not date_payload[4] and not date_payload[5]
        results_by_identity = {result[0]: result for result in date_payload[3]}
        assert installed_item_date_identity(artwork_only_item) not in results_by_identity
        assert results_by_identity[installed_item_date_identity(located_item)][4] is True
        assert results_by_identity[installed_item_date_identity(native_date_item)][1:5] == (
            "2026-08-20",
            "2026-08-20T15:16:17.123456+00:00",
            "fractional-6",
            False,
        )
        assert not located_item.installed_date  # Worker snapshots do not mutate catalog rows.

        # Same-scan native evidence fills WinGet-only framework/non-Store dates
        # without admitting those packages to Store inventory or actions.
        full_name = "Example.Native_1.0.0.0_x64__publisher"
        date_record = {
            "date_only": True, "full_name": full_name,
            "installed_timestamp": "2026-08-20T15:16:17.123456Z",
        }
        dates = windows_package_dates_from_records([date_record])
        assert len(dates) == 1
        assert not windows_package_dates_from_records([
            date_record, {**date_record, "installed_timestamp": "2026-08-21T01:00:00Z"},
        ])
        assert not windows_package_dates_from_records([
            {**date_record, "installed_timestamp": "invalid"},
            {**date_record, "full_name": "x" * 513},
        ])
        date_provider = MicrosoftStoreProvider()
        with patch(f"{__name__}.microsoft_store_package_inventory", return_value=([date_record], "")):
            assert date_provider._native_inventory() == []
            assert date_provider.native_package_dates == dates
        with patch(f"{__name__}.microsoft_store_package_inventory", return_value=([], "unavailable")):
            assert date_provider._native_inventory() == []
            assert not date_provider.native_package_dates  # No stale evidence after failure.
        date_row = inventory_only_item(
            provider="winget", name="Native fixture", package_id="MSIX\\" + full_name,
            current="1.0.0.0", source="winget", scope="user",
        )
        policy_before = (date_row.classification, date_row.selected, date_row.requires_admin)
        wrong_rows = [
            dataclasses.replace(date_row, scope="machine"),
            dataclasses.replace(date_row, scope="unknown"),
            dataclasses.replace(date_row, provider="npm"),
            dataclasses.replace(date_row, package_id="Example.Native"),
            dataclasses.replace(date_row, package_id="MSIX\\" + full_name.replace("x64", "x86")),
            dataclasses.replace(date_row, package_id="MSIX\\" + full_name.replace("1.0.0.0", "2.0.0.0")),
        ]
        assert apply_windows_package_dates(wrong_rows, dates) == 0
        assert apply_windows_package_dates([date_row], dates) == 1
        assert apply_windows_package_dates([date_row], dates) == 0
        assert not date_row.installed_date_is_estimate
        assert date_row.installed_timestamp.endswith(".123456+00:00")
        assert policy_before == (date_row.classification, date_row.selected, date_row.requires_admin)
        date_cache_path = Path(tmp) / "native-date-inventory.json"
        date_store = InstalledInventoryStore(date_cache_path)
        date_scan_time = dt.datetime.now().astimezone()
        date_store.replace(
            [date_row], {"winget"}, date_scan_time, {}, {"winget": date_scan_time.isoformat()},
        )
        reloaded_date = InstalledInventoryStore(date_cache_path).snapshot.items[0]
        assert reloaded_date.installed_timestamp == date_row.installed_timestamp
        assert reloaded_date.installed_timestamp_precision == "fractional-6"
        # A new scan supplies fresh raw rows, so a same-version reinstall can
        # carry a different date without any TTL or persisted-date preference.
        fresh_date_row = dataclasses.replace(date_row, installed_timestamp="", installed_date="")
        refreshed_dates = windows_package_dates_from_records([
            {**date_record, "installed_timestamp": "2026-08-22T01:02:03.654321Z"},
        ])
        assert apply_windows_package_dates([fresh_date_row], refreshed_dates) == 1
        assert fresh_date_row.installed_timestamp != date_row.installed_timestamp
        idle_probe._date_sleuth_active = False
        idle_probe._scan_view_items = {True: {date_row.key: date_row}}
        with patch.object(threading, "Thread") as unused_date_worker:
            idle_probe._run_idle_date_sleuth()
            unused_date_worker.assert_not_called()
    registry_inventory = WindowsInstalledInventory(
        [
            RegistryInstallEntry(
                display_name="Git",
                display_version="2.55.0",
                scope="machine",
                technology="msi",
                install_location=r"C:\Program Files\Git",
                uninstall_key="{12345678-1234-1234-1234-1234567890AB}",
                product_code="{12345678-1234-1234-1234-1234567890AB}",
                estimated_size_kb=262144,
                installed_date="2026-07-16",
                installed_date_source=(
                    "Windows Installer InstallDate (last serviced; original install if "
                    "never serviced)"
                ),
            )
        ]
    )
    enriched_item = registry_inventory.enrich(
        dataclasses.replace(item, name="Git", current="2.55.0", scope="machine")
    )
    assert enriched_item.installed_for == "machine"
    assert enriched_item.installed_technology == "msi"
    assert enriched_item.installed_location == r"C:\Program Files\Git"
    assert enriched_item.product_codes == ("{12345678-1234-1234-1234-1234567890AB}",)
    assert enriched_item.installed_size_kb == 262144
    assert enriched_item.installed_date == "2026-07-16"
    assert not enriched_item.installed_date_is_estimate
    assert enriched_item.installed_date_source.startswith("Windows Installer InstallDate")
    assert enriched_item.metadata_sources == ("arp-uninstall",)
    encoded_arp_item = registry_inventory.enrich(
        dataclasses.replace(
            item,
            name="Display name does not need to match",
            package_id=r"ARP\Machine\X64\{12345678-1234-1234-1234-1234567890AB}",
            current="Unknown",
            scope="machine",
        )
    )
    assert encoded_arp_item.installed_location == r"C:\Program Files\Git"
    assert encoded_arp_item.installed_technology == "msi"
    assert "installed_technology" in item_diagnostic_fields(enriched_item)
    assert item_diagnostic_fields(enriched_item)["installed_size_display"] == "256.0 MB"
    assert "installed_technology" not in enriched_item.to_plan_dict()
    details_probe = object.__new__(WinDevPilotApp)
    details_probe.providers = {"winget": WingetProvider()}
    details_probe.settings = SettingsStore()
    details_probe.settings.data["package_history"] = remember_package_history_event(
        {},
        provider=enriched_item.provider,
        package_id=enriched_item.package_id,
        name=enriched_item.name,
        action="install",
        observed_at="2026-07-16T20:00:00+00:00",
        version=enriched_item.current,
        scope=enriched_item.scope,
        source=enriched_item.source,
    )
    details_probe._update_release_observations = {
        update_observation_identity_key(enriched_item): {
            "provider": enriched_item.provider,
            "package_id": enriched_item.package_id,
            "scope": enriched_item.scope,
            "source": enriched_item.source,
            "available_version": enriched_item.available,
            "last_absent_at": "2026-07-19T12:00:00+00:00",
            "first_seen_at": "2026-07-20T12:00:00+00:00",
            "last_seen_at": "2026-07-20T12:00:00+00:00",
        }
    }
    details_probe._installation_observations = {}
    details_probe.process_is_admin = False
    assert details_probe._run_as_label(enriched_item) == "Admin via UAC"
    details_probe.process_is_admin = True
    assert details_probe._run_as_label(enriched_item) == "Current admin"
    assert details_probe._run_as_label(dataclasses.replace(enriched_item, requires_admin=False)) == (
        "Current admin"
    )
    details_probe.process_is_admin = False
    details_text = WinDevPilotApp.item_details_text(details_probe, enriched_item)
    assert "Installed technology: msi" in details_text
    assert "Installed for: machine" in details_text
    assert "Will run as: Admin via UAC" in details_text
    assert "Installed size: 256.0 MB" in details_text
    assert "Installed / last serviced: 2026-07-16" in details_text
    assert "Installed through WinDevPilot:" in details_text
    assert "Observed release window: after" in details_text
    assert "not a claimed publisher timestamp" in details_text
    precise_native_item = dataclasses.replace(
        enriched_item,
        installed_date="2026-07-16",
        installed_timestamp="2026-07-16T20:21:22.345000+00:00",
        installed_timestamp_precision="fractional-3",
        installed_date_source="Windows PackageManager Package.InstalledDate",
    )
    saved_details_data = details_probe.settings.data
    details_probe.settings.data = {"package_history": {}}
    precise_details = WinDevPilotApp.item_details_text(details_probe, precise_native_item)
    details_probe.settings.data = saved_details_data
    assert local_observation_time(
        precise_native_item.installed_timestamp,
        precise_native_item.installed_timestamp_precision,
    ) in precise_details
    assert "Recorded precision: millisecond" in precise_details
    observed_item = dataclasses.replace(
        enriched_item,
        package_id="Example.ExternallyServiced",
        current="3.0.0",
        available="3.0.0",
        installed_date="",
        installed_date_source="",
    )
    observed_key = update_observation_identity_key(observed_item)
    details_probe._installation_observations = {
        observed_key: {
            "provider": observed_item.provider,
            "package_id": observed_item.package_id,
            "scope": observed_item.scope,
            "source": observed_item.source,
            "version": observed_item.current,
            "state": "present",
            "previous_version": "2.9.0",
            "transition_kind": "version-changed",
            "lower_bound_at": "2026-09-03T08:00:00-04:00",
            "first_seen_at": "2026-09-03T10:00:00-04:00",
            "last_seen_at": "2026-09-03T10:00:00-04:00",
            "last_absent_at": "",
        }
    }
    saved_package_history = details_probe.settings.data["package_history"]
    details_probe.settings.data["package_history"] = {}
    observed_details = details_probe.item_details_text(observed_item)
    assert "Installed / last serviced: ≈ 2026-09-03" in observed_details
    assert "Date/time evidence: Current version changed between complete inventories" in (
        observed_details
    )
    assert "Installed-version observation" in observed_details
    assert "Installed version changed from 2.9.0" in observed_details
    assert "external install, update, repair, or registration change" in observed_details
    details_probe.settings.data["package_history"] = saved_package_history
    details_probe._installation_observations = {}
    steam_inventory_item = UpdateItem(
        provider="winget",
        name="Beat Saber",
        package_id=r"ARP\Machine\X64\Steam App 620980",
        current="Unknown",
        available="Unknown",
        source="winget",
        scope="machine",
        requires_admin=True,
        status="Installed - no update shown",
        classification=CLASS_INVENTORY_ONLY,
        installed_for="machine",
        installed_technology="exe",
        installed_location=r"D:\SteamLibrary\steamapps\common\Beat Saber",
        metadata_sources=("arp-uninstall",),
        metadata_confidence="proven",
    )
    assert is_steam_arp_inventory_item(steam_inventory_item)
    assert installed_channel_display_label(steam_inventory_item, "WinGet") == "Steam"
    assert details_probe._provider_display_label(steam_inventory_item) == "Steam"
    assert details_probe._item_row_values(steam_inventory_item)[6] == "Steam"
    steam_details_text = WinDevPilotApp.item_details_text(
        details_probe,
        steam_inventory_item,
    )
    assert "  Provider: Steam" in steam_details_text
    assert "  Source: Steam uninstall registration" in steam_details_text
    assert "  Discovered through: WinGet installed inventory" in steam_details_text
    assert (
        installed_channel_display_label(
            dataclasses.replace(steam_inventory_item, classification=CLASS_SIMPLE_UPGRADE),
            "WinGet",
        )
        == "WinGet"
    )
    assert "Date/time evidence: Installed by WinDevPilot (verified)" in details_text
    assert "Windows/provider date/time evidence: Windows Installer InstallDate" in details_text
    assert "Product codes: {12345678-1234-1234-1234-1234567890AB}" in details_text
    assert "Icon artwork" not in details_text
    assert "Decision" not in details_text
    registration_inventory = WindowsInstalledInventory(
        [
            RegistryInstallEntry(
                display_name="Approximate App",
                display_version="1.0",
                scope="user",
                technology="exe",
                registration_changed_date="2026-07-18",
                registration_changed_at="2026-07-18T11:12:13.456789+00:00",
            )
        ]
    )
    registration_item = registration_inventory.enrich(
        dataclasses.replace(
            item,
            name="Approximate App",
            package_id="Approximate.App",
            current="1.0",
            scope="user",
        )
    )
    assert registration_item.installed_date == "2026-07-18"
    assert registration_item.installed_timestamp == (
        "2026-07-18T11:12:13.456789+00:00"
    )
    assert registration_item.installed_registration_changed_at == (
        "2026-07-18T11:12:13.456789+00:00"
    )
    assert registration_item.installed_date_is_estimate
    assert "registration last changed" in registration_item.installed_date_source
    details_probe.debug_mode = True
    debug_details_text = WinDevPilotApp.item_details_text(details_probe, enriched_item)
    assert "Decision (debug)" in debug_details_text
    assert "Classification:" in debug_details_text
    assert "Prediction reasons:" in debug_details_text
    details_probe.debug_mode = False
    manifest_fixture = parse_winget_show_metadata(
        """
Found PowerShell 7-preview-x64 [Microsoft.PowerShell.Preview]
Version: 7.7.2.0
Installer Type: msix
Scope: machine
Upgrade Behavior: install
SHA256: deliberately ignored by the conservative label boundary
""",
        package_id="Microsoft.PowerShell.Preview",
        source="winget",
    )
    assert manifest_fixture.installer_types == ("msix",)
    assert manifest_fixture.scopes == ("machine",)
    assert manifest_fixture.upgrade_behaviors == ("install",)
    assert manifest_fixture.raw_fields["name"] == "PowerShell 7-preview-x64"
    assert "sha256" not in manifest_fixture.raw_fields
    version_named_item = dataclasses.replace(
        item,
        name="PowerShell 7-preview-x64 version 1",
        current="1",
    )
    prefer_stable_manifest_name(version_named_item, manifest_fixture)
    assert version_named_item.name == "PowerShell 7-preview-x64"
    winget_show_retry_item = dataclasses.replace(
        item,
        provider="winget",
        package_id="Retry.Manifest",
        source="winget",
    )
    captured_show_commands: list[list[str]] = []
    saved_show_run_capture = globals()["run_capture"]

    def fake_show_run_capture(parts: Sequence[str], *, timeout: int = 900) -> CommandResult:
        captured_show_commands.append(list(parts))
        if len(captured_show_commands) == 1:
            return CommandResult(
                returncode=0x8A150001,
                output="No package found matching input criteria.",
                command=list(parts),
                duration_seconds=0.1,
                timeout_seconds=timeout,
            )
        return CommandResult(
            returncode=0,
            output="Installer:\n  Installer Type: inno\n",
            command=list(parts),
            duration_seconds=0.1,
            timeout_seconds=timeout,
        )

    try:
        globals()["run_capture"] = fake_show_run_capture
        retried_manifest = WingetProvider()._fetch_manifest_metadata(winget_show_retry_item)
    finally:
        globals()["run_capture"] = saved_show_run_capture
    assert len(captured_show_commands) == 2
    assert retried_manifest.returncode == 0
    assert retried_manifest.installer_types == ("inno",)
    assert compatible_winget_installer_technology("msi", {"msi-(zip)"})
    assert compatible_winget_installer_technology("msi", {"burn"})
    assert compatible_winget_installer_technology("msi", {"exe"})
    assert compatible_winget_installer_technology("exe", {"msi"})
    assert compatible_winget_installer_technology("exe", {"inno"})
    assert compatible_winget_installer_technology("exe", {"portable-(zip)"})
    assert compatible_winget_installer_technology("appx", {"msix"})
    assert compatible_winget_installer_technology("msixbundle", {"appxbundle"})
    assert not compatible_winget_installer_technology("msi", {"msix"})
    desktop_bootstrapper_item = apply_winget_preflight_prediction(
        dataclasses.replace(
            enriched_item,
            package_id="Adobe.Acrobat.Reader.64-bit",
            installed_technology="msi",
            installed_for="machine",
            classification=CLASS_SIMPLE_UPGRADE,
            status="Checking details…",
            selected=True,
        ),
        parse_winget_show_metadata(
            "Name: Adobe Acrobat Reader (64-bit)\nInstaller Type: exe\n",
            package_id="Adobe.Acrobat.Reader.64-bit",
        ),
    )
    assert desktop_bootstrapper_item.classification == CLASS_SIMPLE_UPGRADE
    assert desktop_bootstrapper_item.applicability_prediction == PREDICTION_ORDINARY
    assert desktop_bootstrapper_item.status == "Ready"
    assert desktop_bootstrapper_item.selected
    migration_item = apply_winget_preflight_prediction(
        dataclasses.replace(
            enriched_item,
            package_id="Microsoft.PowerShell.Preview",
            installed_technology="msi",
            installed_for="machine",
            product_codes=("{85BDCF78-9FF8-4483-A1EC-2DAC9E8A27E6}",),
        ),
        manifest_fixture,
    )
    assert migration_item.classification == CLASS_MIGRATION_REQUIRED
    assert migration_item.applicability_prediction == PREDICTION_MIGRATION_REQUIRED
    assert migration_item.predicted_hresult == "0x8A15008E"
    assert not migration_item.selected
    for invalid_prediction, invalid_hresult in (
        ("invented-outcome", ""),
        (PREDICTION_UNKNOWN, "not-an-hresult"),
    ):
        try:
            set_applicability_prediction(
                dataclasses.replace(enriched_item),
                invalid_prediction,
                confidence="low",
                source="self-test",
                reasons=("boundary validation fixture",),
                predicted_hresult=invalid_hresult,
            )
        except ValueError:
            pass
        else:
            raise AssertionError("invalid prediction state crossed its boundary")
    assert "classification" not in migration_item.to_plan_dict()
    assert "Guided migration" not in migration_item.to_plan_dict().get("guidance", "")
    migration_details = WinDevPilotApp.item_details_text(details_probe, migration_item)
    assert "PowerShell Preview MSI -> MSIX guided migration" in migration_details
    assert "msiexec.exe /x {85BDCF78-9FF8-4483-A1EC-2DAC9E8A27E6}" in migration_details
    migration_tooltip = WinDevPilotApp.status_tooltip_text(migration_item)
    assert "not a normal in-place update" in migration_tooltip
    assert "installer-technology migrations" in migration_tooltip
    assert "PowerShell Preview MSI migrations" in migration_tooltip
    unrelated_migration_item = dataclasses.replace(
        migration_item,
        package_id="Vendor.Other",
        product_codes=("{11111111-1111-1111-1111-111111111111}",),
    )
    unrelated_migration_details = WinDevPilotApp.item_details_text(
        details_probe, unrelated_migration_item
    )
    assert "Manual migration required" in unrelated_migration_details
    assert "winget install --id Microsoft.PowerShell.Preview" not in unrelated_migration_details
    assert "msiexec.exe" not in unrelated_migration_details
    store_item = apply_winget_preflight_prediction(
        dataclasses.replace(
            enriched_item,
            package_id="XP8BT8DW290MPQ",
            source="msstore",
            classification=CLASS_AMBIGUOUS_IDENTITY,
            status="Ambiguous Store identity",
        ),
        parse_winget_show_metadata("Installer Type: exe\n", package_id="XP8BT8DW290MPQ"),
    )
    assert store_item.applicability_prediction == PREDICTION_STORE_AMBIGUOUS
    assert store_item.status == "Serviced by another app"
    assert not WinDevPilotApp._item_is_bulk_selectable(store_item)
    assert WinDevPilotApp._item_is_actionable(store_item)
    duplicate_item = apply_winget_preflight_prediction(
        dataclasses.replace(enriched_item, classification=CLASS_DUPLICATE_INSTALL),
        parse_winget_show_metadata("Installer Type: exe\n", package_id="Git.Git"),
    )
    assert duplicate_item.applicability_prediction == PREDICTION_DUPLICATE_RESOLUTION
    assert duplicate_item.status == "Installed twice"
    assert WinDevPilotApp._item_is_actionable(duplicate_item)
    assert not WinDevPilotApp._item_is_bulk_selectable(duplicate_item)
    unknown_prediction_item = apply_winget_preflight_prediction(
        dataclasses.replace(enriched_item, installed_for="", installed_technology=""),
        None,
    )
    assert unknown_prediction_item.applicability_prediction == PREDICTION_UNKNOWN
    assert not WinDevPilotApp._item_is_bulk_selectable(unknown_prediction_item)
    assert unknown_prediction_item.classification == CLASS_MANUAL_REVIEW
    assert unknown_prediction_item.status == "Review - manifest unavailable"
    pending_manifest_item = apply_winget_preflight_prediction(
        dataclasses.replace(
            enriched_item,
            package_id="Vendor.Pending",
            installed_technology="exe",
            installed_for="current-user",
            status="Checking details…",
            selected=False,
        ),
        parse_winget_show_metadata(
            "Installer:\n  Installer Type: inno\n",
            package_id="Vendor.Pending",
            source="winget",
        ),
    )
    assert pending_manifest_item.applicability_prediction == PREDICTION_ORDINARY
    assert pending_manifest_item.status == "Ready"
    assert WinDevPilotApp._item_is_bulk_selectable(pending_manifest_item)
    revalidation_item = dataclasses.replace(
        item,
        provider="winget",
        scope="machine",
        requires_admin=True,
        current="2.55.0",
    )
    original_run_capture = globals()["run_capture"]
    try:
        globals()["run_capture"] = lambda *_args, **_kwargs: CommandResult(
            returncode=0,
            output="""
Name       Id       Version  Source
-----------------------------------
Git        Git.Git  2.55.0   winget
""",
            command=[],
        )
        assert revalidate_elevated_winget_machine_target(revalidation_item) is None
        globals()["run_capture"] = lambda *_args, **_kwargs: CommandResult(
            returncode=0,
            output="""
Name       Id       Version  Source
-----------------------------------
Git        Git.Git  2.56.0   winget
""",
            command=[],
        )
        stale_target_failure = revalidate_elevated_winget_machine_target(revalidation_item)
        assert stale_target_failure is not None
        assert not stale_target_failure["success"]
        assert "rescan required" in stale_target_failure["error"]
    finally:
        globals()["run_capture"] = original_run_capture
    for code, transcript, expected_error in (
        (0, "Unrecognized output layout", "recognizable installed-package list"),
        (1, "Warning: source unavailable", "recognizable installed-package list"),
        (0, "", "recognizable installed-package list"),
        (0, "Name       Id       Version  Source\nOther      Other.Id 1.0      winget\n",
         "did not confirm the selected machine package ID"),
        (WINGET_NO_APPLICATIONS_FOUND, "", "registration is no longer present"),
        (WINGET_NO_APPLICATIONS_FOUND - 2**32, "", "registration is no longer present"),
    ):
        with patch(f"{__name__}.run_capture", return_value=CommandResult(code, transcript, [])) as capture:
            revalidation_failure = revalidate_elevated_winget_machine_target(revalidation_item)
        assert revalidation_failure is not None and not revalidation_failure["success"]
        assert expected_error in revalidation_failure["error"]
        assert "rescan required" in revalidation_failure["error"]
        assert capture.call_count == 1 and capture.call_args.args[0][1] == "list"
    for transcript in (
        "Warning: source status\nName       Id       Version  Source\nGit        Git.Git  2.55.0   winget\n",
        "Attention: source\nNom        Identifiant  Version  Origine\n"
        "-------------------------------------------------\nGit        Git.Git      2.55.0   winget\n",
    ):
        with patch(f"{__name__}.run_capture", return_value=CommandResult(0, transcript, [])):
            assert revalidate_elevated_winget_machine_target(revalidation_item) is None
    migration_record = {
        "outcome": "failed",
        "returncode_hex": "0x8A15008E",
        "status_hint": "the update uses a different install technology",
    }
    assert attempt_hold_classification(migration_record) == CLASS_MIGRATION_REQUIRED
    migration_status, migration_guidance = attempt_hold_presentation(migration_record)
    assert "Migration required" in migration_status
    assert "reviewed migration" in migration_guidance
    service_admin_item = UpdateItem(
        provider="winget", name="Claude (Desktop app)", package_id="Anthropic.Claude",
        current="1.40609.1.0", available="1.44121.2", scope="user", source="winget",
        requires_admin=False, selected=True,
    )
    for code in (MSIX_PACKAGED_SERVICE_REQUIRES_ADMIN, MSIX_PACKAGED_SERVICE_REQUIRES_ADMIN - 2**32):
        service_admin_result = CommandResult(returncode=code, output="", command=[])
        for service_provider in (WingetProvider(), MicrosoftStoreProvider()):
            assert not service_provider.succeeded(service_admin_result)
            assert not service_provider.needs_reboot(service_admin_result)
            assert service_provider.outcome(service_admin_result) == "failed"
            assert "packaged service requires administrator" in service_provider.status_hint(service_admin_result)
        with patch(f"{__name__}.collect_winget_installer_logs", return_value=[]):
            service_entry = command_result_entry(
                service_admin_item, WingetProvider(), service_admin_result,
                execution_context="current-user",
            )
        assert service_entry["returncode_hex"] == "0x80073D28"
        assert not service_entry["success"] and not service_entry["remediation"]
        service_hold = build_attempt_hold_record(service_admin_item, service_entry)
        assert service_hold["suppressed"]
        assert attempt_hold_classification(service_hold) == CLASS_MANUAL_REVIEW
        service_status, service_guidance = attempt_hold_presentation(service_hold)
        assert service_status == "Packaged service needs administrator - held"
        assert "owning Windows account" in service_guidance
        assert "will not change the installation scope" in service_guidance
        # Existing records gain the specific explanation without retry or migration.
        legacy_service_hold = {**service_hold, "classification": CLASS_RETRYABLE, "status_hint": ""}
        assert attempt_hold_classification(legacy_service_hold) == CLASS_MANUAL_REVIEW
        assert attempt_hold_presentation(legacy_service_hold) == (service_status, service_guidance)
        held_service_item = apply_stored_selection_policy(
            [dataclasses.replace(service_admin_item)],
            {"attempt_holds": {service_admin_item.candidate_key: legacy_service_hold}},
        )[0]
        assert not held_service_item.selected and not held_service_item.requires_admin
        assert held_service_item.scope == "user" and held_service_item.status == service_status
        assert WingetProvider().build_update_command(held_service_item)[-2:] == ["--scope", "user"]
        for admin_flag in (False, True):
            try:
                validate_elevation_payload({"schema": 1, "items": [
                    dataclasses.replace(held_service_item, requires_admin=admin_flag).to_plan_dict()
                ]}, build_providers())
            except ValueError:
                pass
            else:
                raise AssertionError("a user-scoped packaged service entered the machine batch")
    assert "packaged service" not in WingetProvider().status_hint(
        CommandResult(returncode=1, output="requires administrator", command=[])
    )
    assert attempt_hold_presentation({
        **service_hold, "outcome": "verification-state-change"
    })[0] == "Installed state changed after attempt - held"
    manifest_lag_record = {
        "outcome": "failed",
        "returncode_hex": "0x8A150011",
        "status_hint": "installer hash mismatch; the WinGet manifest is catching up",
    }
    assert attempt_hold_classification(manifest_lag_record) == CLASS_MANIFEST_LAG
    manifest_lag_status, manifest_lag_guidance = attempt_hold_presentation(manifest_lag_record)
    assert "Manifest lag" in manifest_lag_status
    assert "hash" in manifest_lag_guidance.casefold()
    verification_conflict_record = {
        "outcome": "verification-conflict",
        "returncode_hex": "0x00000000",
        "classification": CLASS_VERIFICATION_CONFLICT,
        "status_hint": (
            "The package manager reported success, but a fresh read-only scan still "
            "offered this same exact update."
        ),
    }
    assert (
        attempt_hold_classification(verification_conflict_record)
        == CLASS_VERIFICATION_CONFLICT
    )
    conflict_status, conflict_guidance = attempt_hold_presentation(
        verification_conflict_record
    )
    assert "Verification conflict" in conflict_status
    assert "reported success" in conflict_guidance
    installed_file_hash_record = {
        "outcome": "failed",
        "returncode_hex": "0x8A150204",
        # Prove that corrected stable-code semantics override a classification
        # persisted by an older WinDevPilot build.
        "classification": CLASS_MANIFEST_LAG,
        "status_hint": "the hash of an existing installed file did not match",
    }
    assert attempt_hold_classification(installed_file_hash_record) == CLASS_MANUAL_REPAIR
    assert "manifest" in WINGET_NOTE_BY_CODE[WINGET_INSTALLER_HASH_MISMATCH].casefold()
    assert "existing installed file" in WINGET_NOTE_BY_CODE[
        WINGET_INSTALLED_FILE_HASH_MISMATCH
    ].casefold()
    assert attempt_hold_classification(
        {"returncode_hex": "0x8A150060"}
    ) == CLASS_MANUAL_REVIEW
    assert attempt_hold_classification(
        {"returncode_hex": "0x8A150105"}
    ) == CLASS_RETRYABLE
    verification_state_change_record = {
        "outcome": "verification-state-change",
        "returncode_hex": "0x8A150105",
        "classification": CLASS_MANUAL_REVIEW,
        "status_hint": "Installed state changed while the same target remained offered",
    }
    assert (
        attempt_hold_classification(verification_state_change_record)
        == CLASS_MANUAL_REVIEW
    )
    assert (
        attempt_hold_presentation(verification_state_change_record)[0]
        == "Installed state changed after attempt - held"
    )
    assert attempt_hold_classification(
        {"returncode_hex": "0x8A150114"}
    ) == CLASS_MIGRATION_REQUIRED
    no_applicable_record = {
        "outcome": "not-applicable",
        "returncode_hex": "0x8A150010",
        "status_hint": "No applicable installer found",
    }
    assert attempt_hold_classification(no_applicable_record) == CLASS_SCOPE_OR_APPLICABILITY
    first_hold = build_attempt_hold_record(
        item,
        {
            **migration_record,
            "finished_at": "2026-07-16T20:00:00+00:00",
        },
    )
    repeated_hold = build_attempt_hold_record(
        item,
        {
            **migration_record,
            "finished_at": "2026-07-16T21:00:00+00:00",
        },
        first_hold,
    )
    assert repeated_hold["count"] == 2
    assert repeated_hold["first_seen"] == first_hold["first_seen"]
    assert repeated_hold["last_seen"] == "2026-07-16T21:00:00+00:00"
    assert repeated_hold["suppressed"] is True
    changed_candidate = dataclasses.replace(item, available="3", selected=True)
    assert apply_stored_selection_policy(
        [changed_candidate],
        {"ignored": [], "attempt_holds": {item.candidate_key: {"outcome": "failed"}}},
    )[0].selected
    restored = UpdateItem.from_plan_dict(item.to_plan_dict())
    assert restored.key == item.key
    assert "classification" not in item.to_plan_dict()
    assert item_diagnostic_fields(item)["classification"] == CLASS_SIMPLE_UPGRADE
    unknown_field_plan = item.to_plan_dict()
    unknown_field_plan["command"] = "calc.exe"
    try:
        UpdateItem.from_plan_dict(unknown_field_plan)
    except ValueError:
        pass
    else:
        raise AssertionError("an unknown elevation-plan field was accepted")
    missing_field_plan = item.to_plan_dict()
    missing_field_plan.pop("name")
    try:
        UpdateItem.from_plan_dict(missing_field_plan)
    except ValueError:
        pass
    else:
        raise AssertionError("an elevation-plan item with missing fields was accepted")
    for field, bad_value in (
        ("provider", "winget & calc"),
        ("name", 123),
        ("current", "1 && calc"),
        ("available", "2 && calc"),
        ("source", "https://example.invalid"),
        ("scope", "system"),
        ("requires_admin", "true"),
        ("instance", 1.9),
        ("instance", "not-an-int"),
    ):
        bad_plan = item.to_plan_dict()
        bad_plan[field] = bad_value
        try:
            UpdateItem.from_plan_dict(bad_plan)
        except ValueError:
            pass
        else:
            raise AssertionError(f"unsafe elevation-plan field was accepted: {field}")
    elevation_providers = build_providers()
    assert (
        validate_elevation_payload(
            {"schema": 1, "items": [item.to_plan_dict()]}, elevation_providers
        )[0].key
        == item.key
    )
    wrong_scope_chocolatey = dataclasses.replace(
        item,
        provider="chocolatey",
        source="Chocolatey",
        scope="user",
        requires_admin=True,
    )
    try:
        validate_elevation_payload(
            {"schema": 1, "items": [wrong_scope_chocolatey.to_plan_dict()]},
            elevation_providers,
        )
    except ValueError:
        pass
    else:
        raise AssertionError("a user-scope Chocolatey item crossed elevation")
    try:
        validate_elevation_payload(
            {"schema": 1, "items": [item.to_plan_dict(), item.to_plan_dict()]},
            elevation_providers,
        )
    except ValueError:
        pass
    else:
        raise AssertionError("a duplicate elevation-plan item was accepted")
    try:
        validate_elevation_payload({"schema": 1, "items": []}, elevation_providers)
    except ValueError:
        pass
    else:
        raise AssertionError("an empty elevation plan was accepted")
    command = WingetProvider().build_update_command(item)
    assert "--silent" in command and "--disable-interactivity" in command
    assert "--verbose-logs" in command
    assert "--include-unknown" in command
    assert command[-2:] == ["--scope", "machine"]
    ordinary_exact_command = WingetProvider()._build_update_command(
        dataclasses.replace(
            item,
            scope="user",
            installed_for="current-user",
            requires_admin=False,
        ),
        include_scope=False,
        include_version=False,
    )
    assert "--scope" not in ordinary_exact_command
    assert "--version" not in ordinary_exact_command
    assert ordinary_exact_command[1:5] == ["upgrade", "--id", "Git.Git", "--exact"]
    winget_uninstall = WingetProvider().build_uninstall_command(item)
    assert winget_uninstall[:5] == ["winget", "uninstall", "--id", "Git.Git", "--exact"]
    assert winget_uninstall[winget_uninstall.index("--scope") + 1] == "machine"
    assert "--silent" in winget_uninstall and "--verbose-logs" in winget_uninstall
    assert (
        validate_elevation_payload(
            {"schema": 1, "operation": "uninstall", "items": [item.to_plan_dict()]},
            elevation_providers,
        )[0].key
        == item.key
    )
    try:
        validate_elevation_payload(
            {"schema": 1, "operation": "remove-anything", "items": [item.to_plan_dict()]},
            elevation_providers,
        )
    except ValueError:
        pass
    else:
        raise AssertionError("an unknown elevated operation was accepted")
    not_applicable_result = CommandResult(-1978335189, "No applicable update found", [])
    assert not WingetProvider().succeeded(not_applicable_result)
    assert WingetProvider().outcome(not_applicable_result) == "not-applicable"
    assert "Not applicable" in WingetProvider().status_hint(not_applicable_result)
    not_applicable_entry = command_result_entry(
        item,
        WingetProvider(),
        not_applicable_result,
        execution_context="self-test",
    )
    not_applicable_counts = update_result_counts([not_applicable_entry], 1)
    assert not_applicable_counts["successful"] == 0
    assert not_applicable_counts["not_applicable"] == 1
    assert not_applicable_counts["failed"] == 0
    already_current_result = CommandResult(0x8A15004F, "", [])
    assert WingetProvider().succeeded(already_current_result)
    assert WingetProvider().status_hint(already_current_result) == "Already current"
    reboot_result = CommandResult(0x8A150109, "", [])
    assert WingetProvider().succeeded(reboot_result)
    assert WingetProvider().needs_reboot(reboot_result)
    assert "restart required" in WingetProvider().status_hint(reboot_result)
    canceled_result = CommandResult(0x8A150077, "", [])
    assert not WingetProvider().succeeded(canceled_result)
    assert WingetProvider().outcome(canceled_result) == "canceled"
    assert "Canceled" in WingetProvider().status_hint(canceled_result)
    policy_result = CommandResult(0x8A15003A, "", [])
    assert "Group Policy" in WingetProvider().status_hint(policy_result)
    permission_result = CommandResult(
        0x8A150003,
        (
            "An unexpected error occurred while executing the command:\n"
            'weakly_canonical: Access is denied.: "'
            r"C:\Users\tester\AppData\Local\Microsoft\WinGet\Packages"
            r"\Vendor.Tool_Microsoft.Winget.Source_8wekyb3d8bbwe\tool.exe"
            '"'
        ),
        [],
    )
    assert winget_existing_install_permission_failure_path(permission_result).endswith(
        r"Vendor.Tool_Microsoft.Winget.Source_8wekyb3d8bbwe\tool.exe"
    )
    permission_item = dataclasses.replace(
        item,
        provider="winget",
        package_id="Vendor.Tool",
        installed_location=(
            r"C:\Users\tester\AppData\Local\Microsoft\WinGet\Packages"
            r"\Vendor.Tool_Microsoft.Winget.Source_8wekyb3d8bbwe"
        ),
    )
    permission_entry = command_result_entry(
        permission_item,
        WingetProvider(),
        permission_result,
        execution_context="self-test",
    )
    assert permission_entry["remediation"]["kind"] == "winget-existing-install-permissions"
    assert "package permissions" in permission_entry["status_hint"]
    blocked_file = r"C:\Apps\Example\tool.exe"
    locked_result = CommandResult(
        0x8A150052, f'remove: Access is denied.: "{blocked_file}"', []
    )
    assert failed_file_access_path(locked_result.output) == blocked_file
    assert failed_file_access_path(
        f"[WinError 32] The process cannot access the file because it is being used by another process: '{blocked_file}'"
    ) == blocked_file
    assert failed_file_access_path('Access denied: "C:\\Apps\\Alice\'s tool\\app.exe"').endswith("Alice's tool\\app.exe")
    for bad_output in (
        f'Downloading "{blocked_file}"', 'Access denied: "relative.exe"',
        'Access denied: "\\\\server\\share\\file.exe"',
        'Access denied: "\\\\?\\C:\\Apps\\tool.exe"',
        'Access denied: "C:\\Apps\\..\\tool.exe"',
        'Access denied: "C:\\Apps\\tool.exe:stream"',
        'Access denied: "C:\\Apps\\tool*.exe"',
        'Access denied: "C:\\Apps\\bad\x00.exe"',
    ):
        assert not failed_file_access_path(bad_output), bad_output
    blocker_fixture = {
        "state": "file-users-found", "path": blocked_file,
        "users": [{
            "pid": 123, "name": "tool.exe", "parents": [{
                "pid": 122, "name": "Example IDE.exe", "image": r"C:\Apps\Example IDE.exe",
            }],
        }],
    }
    with patch.dict(globals(), failed_file_blocker_diagnostic=Mock(return_value=blocker_fixture)):
        locked_entry = command_result_entry(
            permission_item, WingetProvider(), locked_result, execution_context="self-test"
        )
        assert not locked_entry["success"] and locked_entry["returncode"] == 0x8A150052
        assert "Example IDE.exe" in locked_entry["status_hint"]
        assert locked_entry["remediation"]["kind"] == "file-in-use"
        lock_hold = build_attempt_hold_record(permission_item, locked_entry)
        lock_status, lock_advice = attempt_hold_presentation(lock_hold)
        assert "last attempt" in lock_status and "may have exited" in lock_advice
        assert "Started through:" in lock_advice and "does not close processes" in lock_advice
        # Lock clues must not downgrade security/policy failures or success.
        failed_file_blocker_diagnostic.reset_mock()
        for code in (0, WINGET_INSTALLER_HASH_MISMATCH, 0x8A15003A):
            command_result_entry(
                permission_item, WingetProvider(), dataclasses.replace(locked_result, returncode=code),
                execution_context="self-test",
            )
        failed_file_blocker_diagnostic.assert_not_called()
    if os.name == "nt":
        with tempfile.TemporaryDirectory(prefix="wdp-file-blocker-") as blocked_temp:
            blocked_target = Path(blocked_temp) / "tool.exe"
            blocked_target.write_bytes(b"fixture, never executed")
            temporary_result = dataclasses.replace(
                locked_result, output=f'Access is denied: "{blocked_target}"'
            )
            with patch.dict(globals(), _windows_file_users=Mock(return_value=[])):
                assert failed_file_blocker_diagnostic(temporary_result)["state"] == "no-users-found"
                _windows_file_users.assert_called_once_with(str(blocked_target))
                with patch.dict(globals(), _portable_path_is_reparse_point=lambda _p: True):
                    assert failed_file_blocker_diagnostic(temporary_result)["state"] == "unsupported-path"
                assert _windows_file_users.call_count == 1
            with patch.dict(globals(), _windows_file_users=Mock(side_effect=OSError("fixture"))):
                assert failed_file_blocker_diagnostic(temporary_result)["state"] == "inconclusive"
            assert not file_blocker_guidance({"state": "inconclusive"})
            assert _FILE_BLOCKER_PROBE_SLOT.acquire(blocking=False)
            try:
                assert failed_file_blocker_diagnostic(temporary_result)["state"] == "busy"
            finally:
                _FILE_BLOCKER_PROBE_SLOT.release()
            slow_probe_release = threading.Event()
            probe_threads: list[threading.Thread] = []
            wait_budgets: list[float | None] = []
            original_join = threading.Thread.join
            def short_probe_join(thread: threading.Thread, timeout: float | None = None) -> None:
                probe_threads.append(thread)
                wait_budgets.append(timeout)
                original_join(thread, 0.01)
            def slow_file_users(_path: str) -> list[dict[str, Any]]:
                slow_probe_release.wait(5)
                return []
            with patch.dict(globals(), _windows_file_users=slow_file_users):
                try:
                    with patch.object(threading.Thread, "join", short_probe_join):
                        timed_report = failed_file_blocker_diagnostic(temporary_result)
                    assert timed_report["state"] == "timed-out" and wait_budgets == [1.0]
                    assert failed_file_blocker_diagnostic(temporary_result)["state"] == "busy"
                finally:
                    slow_probe_release.set()
                    for probe_thread in probe_threads:
                        original_join(probe_thread, 2)
                        assert not probe_thread.is_alive()
                assert timed_report["state"] == "timed-out" and "users" not in timed_report
            with patch.object(threading.Thread, "start", side_effect=RuntimeError("fixture")):
                assert failed_file_blocker_diagnostic(temporary_result)["state"] == "unavailable"
            assert _FILE_BLOCKER_PROBE_SLOT.acquire(blocking=False)
            _FILE_BLOCKER_PROBE_SLOT.release()
            # Exercise native return-count handling and session cleanup without
            # opening a real Restart Manager session in routine self-tests.
            fake_rm = Mock()
            fake_rm.RmStartSession.return_value = 0
            fake_rm.RmRegisterResources.return_value = 0
            fake_rm.RmGetList.return_value = 0
            with patch.object(ctypes, "WinDLL", return_value=fake_rm):
                assert _windows_file_users(str(blocked_target)) == []
                fake_rm.RmEndSession.assert_called_once()
            fake_kernel = Mock()
            fake_kernel.CreateToolhelp32Snapshot.return_value = 99
            fake_kernel.OpenProcess.side_effect = lambda _rights, _inherit, pid: pid
            native_rows = iter(())
            process_times = {1: 300, 2: 200, 3: 100}
            def next_process(_handle: Any, entry_ptr: Any) -> bool:
                value = next(native_rows, None)
                if value is None:
                    return False
                entry_ptr._obj.pid, entry_ptr._obj.parent = value
                return True
            def first_process(handle: Any, entry_ptr: Any) -> bool:
                nonlocal native_rows
                native_rows = iter(((1, 2), (2, 3), (3, 0)))
                return next_process(handle, entry_ptr)
            def fake_process_times(handle: int, created: Any, *_other: Any) -> bool:
                created._obj.dwLowDateTime = process_times[handle]
                return True
            def fake_process_image(handle: int, _flags: Any, buffer: Any, length: Any) -> bool:
                buffer.value = rf"C:\Apps\process{handle}.exe"
                length._obj.value = len(buffer.value)
                return True
            fake_kernel.Process32FirstW.side_effect = first_process
            fake_kernel.Process32NextW.side_effect = next_process
            fake_kernel.GetProcessTimes.side_effect = fake_process_times
            fake_kernel.QueryFullProcessImageNameW.side_effect = fake_process_image
            native_user = {"pid": 1, "started_ticks": 300, "name": "process1"}
            with patch.object(ctypes, "WinDLL", return_value=fake_kernel):
                context = _windows_blocker_process_context([native_user])
                assert [p["pid"] for p in context[0]["parents"]] == [2, 3]
                assert not _windows_blocker_process_context([{**native_user, "started_ticks": 299}])
                process_times[2] = 400  # A reused parent PID is newer than the child.
                assert not _windows_blocker_process_context([native_user])[0]["parents"]
            with patch.object(ctypes, "WinDLL", return_value=fake_rm):
                fake_rm.RmEndSession.reset_mock()
                def too_many_users(_session: Any, needed: Any, _count: Any, _buffer: Any, _reasons: Any) -> int:
                    needed._obj.value = 65
                    return 234
                fake_rm.RmGetList.side_effect = too_many_users
                try:
                    _windows_file_users(str(blocked_target))
                except OSError:
                    pass
                else:
                    raise AssertionError("unbounded Restart Manager result was accepted")
                fake_rm.RmEndSession.assert_called_once()
                fake_rm.RmRegisterResources.return_value = 5
                fake_rm.RmEndSession.reset_mock()
                try:
                    _windows_file_users(str(blocked_target))
                except OSError:
                    pass
                else:
                    raise AssertionError("resource-registration error was ignored")
                fake_rm.RmEndSession.assert_called_once()
    permission_hold = build_attempt_hold_record(permission_item, permission_entry)
    assert attempt_hold_classification(permission_hold) == CLASS_MANUAL_REPAIR
    permission_status, permission_guidance = attempt_hold_presentation(permission_hold)
    assert permission_status == "Existing install permissions need repair"
    assert "do not reset permissions broadly" in permission_guidance
    assert "Create repair script button" in permission_guidance
    crashed_installer_result = CommandResult(
        returncode=0x8A150006,
        output="Installer failed with exit code: 3221225477\n",
        command=[],
    )
    assert "0xC0000005" in winget_installer_failure_hint(crashed_installer_result, [])
    crash_entry = command_result_entry(
        dataclasses.replace(item, provider="winget", package_id="Vendor.CrashedInstaller"),
        WingetProvider(),
        crashed_installer_result,
        execution_context="self-test",
    )
    assert "vendor installer crashed" in crash_entry["status_hint"]
    callback_crash_result = CommandResult(
        returncode=0x8A150006,
        output="Installer failed with exit code: 3221226525\n",
        command=[],
    )
    callback_crash_hint = winget_installer_failure_hint(callback_crash_result, [])
    assert "0xC000041D" in callback_crash_hint
    assert "background services" in callback_crash_hint
    if os.name == "nt":
        display_root = (
            Path(os.environ["LOCALAPPDATA"])
            / "Microsoft"
            / "WinGet"
            / "Packages"
            / "Vendor.Tool_Microsoft.Winget.Source_8wekyb3d8bbwe"
        )
        display_permission_item = dataclasses.replace(
            permission_item,
            installed_location=str(display_root),
        )
        display_permission_entry = {
            **permission_entry,
            "key": display_permission_item.key,
            "remediation": {
                "kind": "winget-existing-install-permissions",
                "blocked_path": str(display_root / "tool.exe"),
                "package_root": str(display_root),
                "requires_manual_elevation": True,
            },
        }
        display_permission_hold = build_attempt_hold_record(
            display_permission_item,
            display_permission_entry,
        )
        details_probe.settings.data["attempt_holds"] = {
            display_permission_item.candidate_key: display_permission_hold
        }
        permission_details = WinDevPilotApp.item_details_text(
            details_probe,
            display_permission_item,
        )
        assert "WinGet permission repair" in permission_details
        assert "use Create repair script below" in permission_details
        assert "does not run automatically" in permission_details
        assert "release this package hold" in permission_details
        details_probe.settings.data["attempt_holds"] = {}
    winget_retry_item = dataclasses.replace(
        item,
        provider="winget",
        package_id="Vendor.Tool",
        source="winget",
        scope="user",
        requires_admin=False,
        installed_for="current-user",
        installed_technology="exe",
        available_technology="inno",
        available_scope="",
        classification=CLASS_SIMPLE_UPGRADE,
    )

    captured_winget_commands: list[list[str]] = []
    real_run_capture = globals()["run_capture"]

    def fake_winget_run_capture(parts: Sequence[str], *, timeout: int = 900) -> CommandResult:
        captured_winget_commands.append(list(parts))
        if "--scope" in parts:
            return CommandResult(
                returncode=0x8A150010,
                output="No applicable installer found",
                command=list(parts),
                started_at="2026-07-20T00:00:00+00:00",
                finished_at="2026-07-20T00:00:01+00:00",
                duration_seconds=1.0,
                timeout_seconds=timeout,
            )
        return CommandResult(
            returncode=0,
            output="Installed",
            command=list(parts),
            started_at="2026-07-20T00:00:01+00:00",
            finished_at="2026-07-20T00:00:03+00:00",
            duration_seconds=2.0,
            timeout_seconds=timeout,
        )

    try:
        globals()["run_capture"] = fake_winget_run_capture
        fallback_result = WingetProvider().update(winget_retry_item)
    finally:
        globals()["run_capture"] = real_run_capture
    assert fallback_result.returncode == 0
    assert len(captured_winget_commands) == 2
    assert "--scope" in captured_winget_commands[0]
    assert "--scope" not in captured_winget_commands[1]
    assert "retried a proven single-scope package" in fallback_result.output
    assert "Unscoped pinned retry" in fallback_result.output
    assert [attempt["strategy"] for attempt in fallback_result.attempts] == [
        "scoped-pinned",
        "unscoped-pinned",
    ]
    assert fallback_result.attempts[0]["returncode_hex"] == "0x8A150010"
    assert fallback_result.attempts[1]["duration_seconds"] == 2.0
    fallback_diagnostics = command_diagnostic_fields(fallback_result)
    assert len(fallback_diagnostics["attempts"]) == 2
    assert "output" not in fallback_diagnostics["attempts"][0]
    adobe_retry_item = dataclasses.replace(
        winget_retry_item,
        package_id="Adobe.Acrobat.Reader.64-bit",
        scope="machine",
        installed_for="machine",
        installed_technology="msi",
        available_technology="exe",
        requires_admin=True,
    )
    captured_adobe_commands: list[list[str]] = []

    def fake_adobe_winget_run_capture(
        parts: Sequence[str], *, timeout: int = 900
    ) -> CommandResult:
        captured_adobe_commands.append(list(parts))
        return CommandResult(
            returncode=0x8A15002B if "--scope" in parts else 0,
            output=(
                "No applicable installer found"
                if "--scope" in parts
                else "Installed through unscoped exact-ID selection"
            ),
            command=list(parts),
            duration_seconds=0.1,
            timeout_seconds=timeout,
        )

    try:
        globals()["run_capture"] = fake_adobe_winget_run_capture
        adobe_fallback_result = WingetProvider().update(adobe_retry_item)
    finally:
        globals()["run_capture"] = real_run_capture
    assert adobe_fallback_result.returncode == 0
    assert len(captured_adobe_commands) == 2
    assert "--scope" in captured_adobe_commands[0]
    assert "--scope" not in captured_adobe_commands[1]
    assert "--version" in captured_adobe_commands[1]
    assert [attempt["strategy"] for attempt in adobe_fallback_result.attempts] == [
        "scoped-pinned",
        "unscoped-pinned",
    ]
    assert adobe_fallback_result.attempts[0]["returncode_hex"] == "0x8A15002B"
    captured_scope_mismatch_commands: list[list[str]] = []

    def fake_scope_mismatch_run_capture(
        parts: Sequence[str], *, timeout: int = 900
    ) -> CommandResult:
        captured_scope_mismatch_commands.append(list(parts))
        return CommandResult(
            returncode=0x8A150010,
            output=(
                "No applicable installer found\n"
                "Installer scope does not match currently installed scope: Machine != User"
            ),
            command=list(parts),
            duration_seconds=0.1,
            timeout_seconds=timeout,
        )

    try:
        globals()["run_capture"] = fake_scope_mismatch_run_capture
        scope_mismatch_result = WingetProvider().update(winget_retry_item)
    finally:
        globals()["run_capture"] = real_run_capture
    assert len(captured_scope_mismatch_commands) == 1
    assert len(scope_mismatch_result.attempts) == 1
    assert winget_scope_mismatch_evidence(scope_mismatch_result) == ("Machine", "User")
    assert "Machine installer" in winget_installer_failure_hint(scope_mismatch_result, [])
    captured_unpinned_commands: list[list[str]] = []

    def fake_unpinned_winget_run_capture(
        parts: Sequence[str], *, timeout: int = 900
    ) -> CommandResult:
        captured_unpinned_commands.append(list(parts))
        return CommandResult(
            returncode=0x8A150010 if "--version" in parts else 0,
            output=(
                "No applicable installer found"
                if "--version" in parts
                else "Installed through ordinary exact-ID selection"
            ),
            command=list(parts),
            duration_seconds=0.1,
            timeout_seconds=timeout,
        )

    try:
        globals()["run_capture"] = fake_unpinned_winget_run_capture
        unpinned_result = WingetProvider().update(winget_retry_item)
    finally:
        globals()["run_capture"] = real_run_capture
    assert unpinned_result.returncode == 0x8A150010
    assert len(captured_unpinned_commands) == 2
    assert "--scope" in captured_unpinned_commands[0]
    assert "--scope" not in captured_unpinned_commands[1]
    assert all("--version" in command for command in captured_unpinned_commands)
    assert "has not substituted a different version" in unpinned_result.output
    assert [attempt["strategy"] for attempt in unpinned_result.attempts] == [
        "scoped-pinned",
        "unscoped-pinned",
    ]
    classified_entry = command_result_entry(
        item,
        WingetProvider(),
        already_current_result,
        execution_context="self-test",
    )
    classified_counts = update_result_counts([classified_entry], 1)
    assert classified_counts["successful"] == 1
    assert classified_counts["already_current"] == 1
    assert classified_counts["updated"] == 0
    assert validate_elevation_results([classified_entry], [item])[0]["key"] == item.key
    try:
        validate_elevation_results([classified_entry, classified_entry], [item])
    except RuntimeError:
        pass
    else:
        raise AssertionError("duplicate elevated results were accepted")
    pending_item = UpdateItem(
        "winget", "Pending", "Pending.Package", "1", "2", "winget"
    )
    verification_fixture = reconcile_verification_results(
        {
            item.key: {
                "item": item_diagnostic_fields(item),
                "result": {"success": True, "outcome": "updated"},
            },
            pending_item.key: {
                "item": item_diagnostic_fields(pending_item),
                "result": {"success": False, "outcome": "not-applicable"},
            },
        },
        [pending_item],
        set(),
    )
    assert len(verification_fixture["no_longer_offered"]) == 1
    assert len(verification_fixture["still_pending"]) == 1
    assert (
        verification_fixture["status_by_key"][pending_item.key]
        == "Needs different scope or installer"
    )
    attempted_transition = UpdateItem(
        "winget", "Successor", "Vendor.Successor", "1", "2", "winget"
    )
    successor_transition = dataclasses.replace(
        attempted_transition, current="2", available="3"
    )
    successor_reconciliation = reconcile_verification_results(
        {
            attempted_transition.key: {
                "item": item_diagnostic_fields(attempted_transition),
                "result": {"success": True, "outcome": "updated"},
            }
        },
        [successor_transition],
        set(),
    )
    assert len(successor_reconciliation["successor_offered"]) == 1
    assert not successor_reconciliation["contradicted_success"]
    assert successor_reconciliation["status_by_key"][attempted_transition.key].startswith(
        "Newer update available"
    )
    unchanged_successor_reconciliation = reconcile_verification_results(
        {
            attempted_transition.key: {
                "item": item_diagnostic_fields(attempted_transition),
                "result": {"success": True, "outcome": "updated"},
            }
        },
        [dataclasses.replace(attempted_transition, available="3")],
        set(),
    )
    assert not unchanged_successor_reconciliation["successor_offered"]
    assert len(unchanged_successor_reconciliation["contradicted_success"]) == 1
    assert (
        unchanged_successor_reconciliation["status_by_key"][attempted_transition.key]
        == "Installed version unchanged after reported success - held"
    )
    same_candidate_reconciliation = reconcile_verification_results(
        {
            attempted_transition.key: {
                "item": item_diagnostic_fields(attempted_transition),
                "result": {"success": True, "outcome": "updated"},
            }
        },
        [dataclasses.replace(attempted_transition)],
        set(),
    )
    assert len(same_candidate_reconciliation["contradicted_success"]) == 1
    cosmetic_target_reconciliation = reconcile_verification_results(
        {
            attempted_transition.key: {
                "item": item_diagnostic_fields(attempted_transition),
                "result": {"success": True, "outcome": "updated"},
            }
        },
        [dataclasses.replace(attempted_transition, available="2.0.0")],
        set(),
    )
    assert len(cosmetic_target_reconciliation["contradicted_success"]) == 1
    assert not cosmetic_target_reconciliation["successor_offered"]
    installed_state_reconciliation = reconcile_verification_results(
        {
            attempted_transition.key: {
                "item": item_diagnostic_fields(attempted_transition),
                "result": {"success": False, "outcome": "failed"},
            }
        },
        [dataclasses.replace(attempted_transition, current="1.5")],
        set(),
    )
    assert len(installed_state_reconciliation["installed_state_changed"]) == 1
    assert (
        installed_state_reconciliation["status_by_key"][attempted_transition.key]
        == "Installed state changed after attempt - held"
    )
    changed_target_reconciliation = reconcile_verification_results(
        {
            attempted_transition.key: {
                "item": item_diagnostic_fields(attempted_transition),
                "result": {"success": True, "outcome": "updated"},
            }
        },
        [dataclasses.replace(attempted_transition, available="preview")],
        set(),
    )
    assert len(changed_target_reconciliation["target_changed"]) == 1
    assert not changed_target_reconciliation["successor_offered"]
    reboot_reconciliation = reconcile_verification_results(
        {
            attempted_transition.key: {
                "item": item_diagnostic_fields(attempted_transition),
                "result": {
                    "success": True,
                    "outcome": "updated",
                    "needs_reboot": True,
                },
            }
        },
        [dataclasses.replace(attempted_transition)],
        set(),
    )
    assert len(reboot_reconciliation["restart_pending"]) == 1
    assert not reboot_reconciliation["contradicted_success"]
    for installed_version in (attempted_transition.current, successor_transition.current):
        reboot_changed_target = reconcile_verification_results(
            {
                attempted_transition.key: {
                    "item": item_diagnostic_fields(attempted_transition),
                    "result": {
                        "success": True,
                        "outcome": "updated",
                        "needs_reboot": True,
                    },
                }
            },
            [dataclasses.replace(successor_transition, current=installed_version)],
            set(),
        )
        assert len(reboot_changed_target["restart_pending"]) == 1
        assert not reboot_changed_target["successor_offered"]
        assert not reboot_changed_target["contradicted_success"]
        assert reboot_changed_target["status_by_key"][attempted_transition.key] == (
            "Restart required before evaluating changed update target"
        )
    cancelled_reconciliation = reconcile_verification_results(
        {
            attempted_transition.key: {
                "item": item_diagnostic_fields(attempted_transition),
                "result": {"success": True, "outcome": "updated"},
            }
        },
        [],
        {WingetProvider.key},
    )
    assert len(cancelled_reconciliation["unverified"]) == 1
    assert not cancelled_reconciliation["no_longer_offered"]
    assert WinDevPilotApp._log_visual_tag("Update run finished: 2 updated") == "log_success"
    assert (
        WinDevPilotApp._log_visual_tag("Update run finished: 5 not applicable") == "log_warning"
    )
    assert (
        WinDevPilotApp._log_visual_tag("Update run finished: 5 not applicable, 1 failed")
        == "log_failure"
    )
    assert WinDevPilotApp._log_visual_tag("Git: Updated (exit 0)") == "log_success"
    assert (
        WinDevPilotApp._log_visual_tag("ExampleApp: Not applicable \u2022 scope mismatch")
        == "log_warning"
    )
    assert WinDevPilotApp._log_visual_tag("Tool: Failed (exit 1)") == "log_failure"
    assert (
        WinDevPilotApp._log_visual_tag(
            "Attempted-package refresh — WinGet: 2 no longer offered, 0 still "
            "offered, 0 newer offer(s), 0 changed target(s), 0 awaiting restart, "
            "0 unverified (0.2s); inventory continues"
        )
        == "log_success"
    )
    assert (
        WinDevPilotApp._log_visual_tag(
            "Attempted-package refresh — WinGet: 0 no longer offered, 0 still "
            "offered, 0 newer offer(s), 0 changed target(s), 0 awaiting restart, "
            "2 unverified (0.0s); inventory continues"
        )
        == "log_warning"
    )
    assert (
        WinDevPilotApp._log_visual_tag(
            "Verification finished: 2 no longer offered, 0 still offered after "
            "attempt, 0 newer offer(s), 0 changed target(s), 0 awaiting restart, "
            "0 unverified"
        )
        == "log_success"
    )
    assert (
        WinDevPilotApp._log_visual_tag(
            "Verification finished: 0 no longer offered, 0 still offered after "
            "attempt, 0 newer offer(s), 0 changed target(s), 0 awaiting restart, "
            "1 unverified"
        )
        == "log_warning"
    )
    chocolatey_command = ChocolateyProvider().build_update_command(item)
    assert "--fail-on-not-installed" in chocolatey_command
    assert "--verbose" in chocolatey_command and "--limit-output" not in chocolatey_command
    assert chocolatey_command[chocolatey_command.index("--version") + 1] == "2"
    assert ChocolateyProvider().build_uninstall_command(item) == [
        "choco",
        "uninstall",
        "Git.Git",
        "--yes",
        "--no-progress",
        "--verbose",
    ]
    unsafe_chocolatey = dataclasses.replace(item, available="2 & calc")
    try:
        ChocolateyProvider().build_update_command(unsafe_chocolatey)
    except ValueError:
        pass
    else:
        raise AssertionError("an unsafe Chocolatey version was accepted")
    assert classify_winget_scopes(
        "Git.Git",
        "1",
        {("git.git", "1")},
        {"git.git"},
        {("git.git", "1")},
        {"git.git"},
    ) == ("user", "machine")
    assert not classify_winget_scopes("Unknown.Package", "1", set(), set(), set(), set())
    next_instance = dataclasses.replace(item, instance=3)
    assert next_instance.key != item.key
    assert next_instance.ignore_key != item.ignore_key
    first_identity = dataclasses.replace(item, package_id="First.Package", instance=8)
    second_identity = dataclasses.replace(item, package_id="Second.Package", instance=19)
    normalized_identities = stable_identity_instances(
        [first_identity, second_identity]
    )
    assert [value.instance for value in normalized_identities] == [0, 0]
    assert stable_identity_instances([second_identity])[0].key == normalized_identities[1].key
    scan_delta = update_scan_delta(
        [item],
        [dataclasses.replace(item, available="3"), next_instance],
    )
    assert scan_delta == {"new": 1, "resolved": 0, "target_changed": 1}
    unknown_scope_item = dataclasses.replace(
        item, scope="unknown", requires_admin=False, selected=False
    )
    assert not WinDevPilotApp._item_is_actionable(unknown_scope_item)
    selection_probe = object.__new__(WinDevPilotApp)
    inventory_item = dataclasses.replace(
        item,
        package_id="Inventory.Only",
        classification=CLASS_INVENTORY_ONLY,
        selected=False,
    )
    selection_probe.items = {
        unknown_scope_item.key: unknown_scope_item,
        inventory_item.key: inventory_item,
    }
    selection_probe._active_scan_generation = 7
    selection_probe._selection_block_notices = set()
    selection_notices: list[str] = []
    selection_summaries: list[str] = []
    selection_banners: list[str] = []
    selection_probe._notify_user = lambda message, **_kwargs: selection_notices.append(message)
    selection_probe.summary_var = type(
        "SummaryProbe",
        (),
        {"set": lambda _self, value: selection_summaries.append(value)},
    )()
    selection_probe._show_notification_banner = (
        lambda message, **_kwargs: selection_banners.append(message)
    )
    selection_probe._report_blocked_selection([unknown_scope_item], changed=0)
    selection_probe._report_blocked_selection([unknown_scope_item], changed=0)
    assert len(selection_notices) == 1
    assert "installation scope could not be proven" in selection_notices[0]
    assert selection_summaries == ["Some packages were left unselected"]
    assert selection_banners == []
    selection_probe._report_blocked_selection([inventory_item], changed=0)
    assert len(selection_notices) == 2
    assert "does not select update candidates" in selection_notices[1]
    notification_probe = object.__new__(WinDevPilotApp)
    notification_probe.summary_var = type(
        "NotificationSummaryProbe", (), {"set": lambda _self, _value: None}
    )()
    notification_probe._append_log = lambda *_args, **_kwargs: None
    notification_banners: list[tuple[str, str]] = []
    notification_probe._show_notification_banner = (
        lambda message, *, level: notification_banners.append((message, level))
    )
    notification_probe._notify_user("Advisory", level="warning")
    assert notification_banners == []
    notification_probe._notify_user("Failure", level="error")
    assert notification_banners == [("Failure", "error")]
    winget_fixture_provider = WingetProvider()
    pin_fixture = """\
Name         Id                  Version  Type
----------------------------------------------
Example App  Example.VendorApp   1.0      Blocking
"""
    saved_pin_run_capture = globals()["run_capture"]
    try:
        globals()["run_capture"] = lambda *_args, **_kwargs: CommandResult(
            returncode=0,
            output=pin_fixture,
            command=["winget", "pin", "list"],
        )
        assert winget_fixture_provider._discover_pin_types() == {
            "example.vendorapp": "blocking"
        }
    finally:
        globals()["run_capture"] = saved_pin_run_capture
    winget_fixture_provider._pin_types_by_id = {"example.vendorapp": "blocking"}
    pinned_items = winget_fixture_provider._items_from_rows(
        [
            {
                "Name": "Example App",
                "Id": "Example.VendorApp",
                "Version": "1.0",
                "Available": "2.0",
                "Source": "winget",
                "_Scope": "user",
            }
        ],
        set(),
        set(),
        {("example.vendorapp", "1.0")},
        {"example.vendorapp"},
    )
    assert len(pinned_items) == 1
    assert pinned_items[0].status == "Pinned — left unchanged"
    assert pinned_items[0].classification == CLASS_POLICY_BLOCKED
    assert not pinned_items[0].selected
    assert not WinDevPilotApp._item_is_actionable(pinned_items[0])
    untrusted_pin_provider = WingetProvider()
    try:
        globals()["run_capture"] = lambda *_args, **_kwargs: CommandResult(
            returncode=0,
            output="Unrecognized pin response",
            command=["winget", "pin", "list"],
        )
        assert not untrusted_pin_provider._discover_pin_types()
    finally:
        globals()["run_capture"] = saved_pin_run_capture
    assert untrusted_pin_provider._pin_state_untrusted
    untrusted_pin_items = untrusted_pin_provider._items_from_rows(
        [
            {
                "Name": "Example App",
                "Id": "Example.VendorApp",
                "Version": "1.0",
                "Available": "2.0",
                "Source": "winget",
                "_Scope": "user",
            }
        ],
        set(),
        set(),
        {("example.vendorapp", "1.0")},
        {"example.vendorapp"},
    )
    assert len(untrusted_pin_items) == 1
    assert untrusted_pin_items[0].status == "Pin state unavailable — review"
    assert untrusted_pin_items[0].classification == CLASS_MANUAL_REVIEW
    assert not untrusted_pin_items[0].selected
    assert not WinDevPilotApp._item_is_bulk_selectable(untrusted_pin_items[0])
    assert WinDevPilotApp._item_needs_review(untrusted_pin_items[0])
    winget_fixture_provider._pin_types_by_id = {}
    dual_scope_items = winget_fixture_provider._items_from_rows(
        [
            {
                "Name": "Git",
                "Id": "Git.Git",
                "Version": "1",
                "Available": "2",
                "Source": "winget",
            },
            {
                "Name": "Truncated",
                "Id": "Bad.Package…",
                "Version": "1",
                "Available": "2",
                "Source": "winget",
            },
        ],
        {("git.git", "1")},
        {"git.git"},
        {("git.git", "1")},
        {"git.git"},
    )
    assert [entry.scope for entry in dual_scope_items] == ["user", "machine"]
    assert dual_scope_items[0].key != dual_scope_items[1].key
    assert not any(entry.selected for entry in dual_scope_items)
    assert all("Duplicate" in entry.status for entry in dual_scope_items)
    assert not any(WinDevPilotApp._item_is_bulk_selectable(entry) for entry in dual_scope_items)
    assert any("truncated" in warning.casefold() for warning in winget_fixture_provider.warnings)
    stale_user_duplicate = WingetProvider()._items_from_rows(
        [
            {
                "Name": "Git",
                "Id": "Git.Git",
                "Version": "1",
                "Available": "2",
                "Source": "winget",
                "_Scope": "user",
            }
        ],
        {("git.git", "2")},
        {"git.git"},
        {("git.git", "1")},
        {"git.git"},
    )
    assert len(stale_user_duplicate) == 1
    assert stale_user_duplicate[0].scope == "user"
    assert stale_user_duplicate[0].classification == CLASS_DUPLICATE_INSTALL
    assert not stale_user_duplicate[0].selected
    assert WinDevPilotApp._item_is_actionable(stale_user_duplicate[0])
    assert not WinDevPilotApp._item_is_bulk_selectable(stale_user_duplicate[0])
    assert WinDevPilotApp._item_needs_review(stale_user_duplicate[0])
    assert "both current-user and machine" in stale_user_duplicate[0].guidance
    ordinary_third_party_items = WingetProvider()._items_from_rows(
        [
            {
                "Name": "ExampleApp",
                "Id": "Example.VendorApp",
                "Version": "1",
                "Available": "2",
                "Source": "winget",
                "_Scope": "user",
            }
        ],
        set(),
        set(),
        {("example.vendorapp", "1")},
        {"example.vendorapp"},
    )
    assert len(ordinary_third_party_items) == 1
    assert ordinary_third_party_items[0].classification == CLASS_SIMPLE_UPGRADE
    assert ordinary_third_party_items[0].selected
    assert not ordinary_third_party_items[0].guidance_url
    edge_policy_items = WingetProvider()._items_from_rows(
        [
            {
                "Name": "Microsoft Edge",
                "Id": "Microsoft.Edge",
                "Version": "150.0.4078.65",
                "Available": "150.0.4078.83",
                "Source": "winget",
                "_Scope": "machine",
            }
        ],
        {("microsoft.edge", "150.0.4078.65")},
        {"microsoft.edge"},
        set(),
        set(),
    )
    assert len(edge_policy_items) == 1
    assert edge_policy_items[0].classification == CLASS_VENDOR_MANAGED
    assert not WinDevPilotApp._item_is_recommended_selectable(edge_policy_items[0])
    assert "Edge updates itself" in edge_policy_items[0].status
    gameinput_policy_items = WingetProvider()._items_from_rows(
        [
            {
                "Name": "Microsoft GameInput",
                "Id": "Microsoft.GameInput",
                "Version": "3.3.195.0",
                "Available": "3.4.218",
                "Source": "winget",
                "_Scope": "machine",
            }
        ],
        {("microsoft.gameinput", "3.3.195.0")},
        {"microsoft.gameinput"},
        set(),
        set(),
    )
    assert len(gameinput_policy_items) == 1
    assert gameinput_policy_items[0].classification == CLASS_MANUAL_REVIEW
    assert not WinDevPilotApp._item_is_recommended_selectable(gameinput_policy_items[0])
    assert "review manually" in gameinput_policy_items[0].status
    scoped_winget_items = WingetProvider()._items_from_rows(
        [
            {
                "Name": "Zen user",
                "Id": "Zen-Team.Zen-Browser",
                "Version": "1.19.5b",
                "Available": "1.21.7b",
                "Source": "winget",
                "_Scope": "user",
            },
            {
                "Name": "Zen machine",
                "Id": "Zen-Team.Zen-Browser",
                "Version": "1.19.1b",
                "Available": "1.21.7b",
                "Source": "winget",
                "_Scope": "machine",
            },
        ],
        {("zen-team.zen-browser", "1.19.1b")},
        {"zen-team.zen-browser"},
        {("zen-team.zen-browser", "1.19.5b")},
        {"zen-team.zen-browser"},
    )
    assert [(entry.current, entry.scope) for entry in scoped_winget_items] == [
        ("1.19.5b", "user"),
        ("1.19.1b", "machine"),
    ]
    assert not any(entry.selected for entry in scoped_winget_items)
    ambiguous_store_items = WingetProvider()._items_from_rows(
        [
            {
                "Name": "Meeting Add-in",
                "Id": "Store.Product",
                "Version": "1",
                "Available": "2",
                "Source": "msstore",
                "_Scope": "machine",
            }
        ],
        {("store.product", "1")},
        {"store.product"},
        set(),
        {"store.product"},
        {"store.product": {"meeting add-in", "main application"}},
    )
    assert len(ambiguous_store_items) == 1
    assert not ambiguous_store_items[0].selected
    assert ambiguous_store_items[0].status == "Ambiguous Store identity"
    assert ambiguous_store_items[0].scope == "machine"
    assert not ambiguous_store_items[0].requires_admin
    assert not WinDevPilotApp._item_is_bulk_selectable(ambiguous_store_items[0])
    store_plan_item = dataclasses.replace(ambiguous_store_items[0], requires_admin=True)
    try:
        validate_elevation_payload(
            {"schema": 1, "items": [store_plan_item.to_plan_dict()]},
            elevation_providers,
        )
    except ValueError as exc:
        assert "Store items" in str(exc)
    else:
        raise AssertionError("a Microsoft Store item crossed the elevation boundary")
    rustup_fixture_provider = RustupProvider()
    rustup_self_update_only = (
        "stable-x86_64-pc-windows-msvc - up to date: 1.98.0 "
        "(88d9e12ae 2026-08-18)\n"
        "rustup - update available : 1.29.0 -> 1.29.1\n"
    )
    assert rustup_fixture_provider._has_recognized_self_update(rustup_self_update_only)
    assert not rustup_fixture_provider._items_from_output(rustup_self_update_only)
    assert rustup_fixture_provider._check_result_is_acceptable(
        RUSTUP_UPDATE_AVAILABLE,
        rustup_self_update_only,
        [],
    )
    assert not rustup_fixture_provider._check_result_is_acceptable(
        RUSTUP_UPDATE_AVAILABLE,
        "stable-x86_64-pc-windows-msvc - up to date: 1.98.0\n",
        [],
    )
    assert not rustup_fixture_provider._has_recognized_self_update(
        "stable-x86_64-pc-windows-msvc - up to date: 1.98.0\n"
    )
    rustup_items = rustup_fixture_provider._items_from_output(
        "stable-x86_64-pc-windows-msvc - update available: "
        "1.96.0 (old 2026-05-25) -> 1.97.1 (new 2026-07-14)\n"
        "rustup - up to date : 1.29.0\n"
    )
    assert len(rustup_items) == 1
    assert rustup_items[0].package_id == "stable-x86_64-pc-windows-msvc"
    assert rustup_items[0].current == "1.96.0 (old 2026-05-25)"
    assert rustup_items[0].available == "1.97.1 (new 2026-07-14)"
    nightly_rustup_items = rustup_fixture_provider._items_from_output(
        "nightly-x86_64-pc-windows-msvc - update available: "
        "1.99.0-nightly (504869653 2026-08-03) -> "
        "1.99.0-nightly (771916f90 2026-08-08)\n"
    )
    assert len(nightly_rustup_items) == 1
    assert nightly_rustup_items[0].current.endswith("(504869653 2026-08-03)")
    assert nightly_rustup_items[0].available.endswith("(771916f90 2026-08-08)")
    previous_nightly_item = dataclasses.replace(
        nightly_rustup_items[0],
        available="1.99.0-nightly (1ed2df61a 2026-08-04)",
    )
    assert nightly_rustup_items[0].candidate_key != previous_nightly_item.candidate_key
    rustup_command = rustup_fixture_provider.build_update_command(rustup_items[0])
    assert rustup_command[-1] == "--no-self-update"
    assert "--verbose" not in rustup_command
    rustup_fixture_provider.debug_mode = True
    assert "--verbose" in rustup_fixture_provider.build_update_command(rustup_items[0])
    assert rustup_fixture_provider.build_uninstall_command(rustup_items[0]) == [
        "rustup",
        "toolchain",
        "uninstall",
        "stable-x86_64-pc-windows-msvc",
    ]
    damaged_rustup_result = CommandResult(
        returncode=1,
        output=(
            "info: rolling back changes\n"
            "error: failure removing component 'rustc-x86_64-pc-windows-msvc', "
            "directory does not exist: 'bin\\rustc_driver-deadbeef.dll'\n"
        ),
        command=["rustup", "update", "nightly-x86_64-pc-windows-msvc"],
        requested_command=["rustup", "update", "nightly-x86_64-pc-windows-msvc"],
    )
    assert rustup_damaged_toolchain_evidence(damaged_rustup_result.output) == (
        "rustc-x86_64-pc-windows-msvc",
        r"bin\rustc_driver-deadbeef.dll",
    )
    assert "reinstall manually" in rustup_fixture_provider.status_hint(
        damaged_rustup_result
    )
    damaged_rustup_entry = command_result_entry(
        nightly_rustup_items[0],
        rustup_fixture_provider,
        damaged_rustup_result,
        execution_context="current-user",
    )
    assert damaged_rustup_entry["remediation"]["kind"] == "rustup-damaged-toolchain"
    assert damaged_rustup_entry["remediation"]["automatic_repair"] is False
    damaged_rustup_hold = build_attempt_hold_record(
        nightly_rustup_items[0],
        damaged_rustup_entry,
    )
    assert attempt_hold_classification(damaged_rustup_hold) == CLASS_MANUAL_REPAIR
    damaged_status, damaged_guidance = attempt_hold_presentation(damaged_rustup_hold)
    assert "Damaged Rust toolchain" in damaged_status
    assert "separate system repair" in damaged_guidance
    held_rustup_item = apply_stored_selection_policy(
        [dataclasses.replace(nightly_rustup_items[0])],
        {
            "ignored": [],
            "attempt_holds": {
                nightly_rustup_items[0].candidate_key: damaged_rustup_hold,
            },
        },
    )[0]
    assert held_rustup_item.classification == CLASS_MANUAL_REPAIR
    assert "separate manual system repair" in WinDevPilotApp.status_tooltip_text(
        held_rustup_item
    )
    vcpkg_fixture_provider = VcpkgProvider()
    assert VcpkgProvider._classic_instance_unavailable(
        "Could not locate a manifest (vcpkg.json) above the current working directory.\n"
        "This vcpkg distribution does not have a classic mode instance."
    )
    assert not VcpkgProvider._classic_instance_unavailable(
        "error: failed to download registry metadata"
    )
    vcpkg_items = vcpkg_fixture_provider._items_from_output(
        """
The following packages will be rebuilt:
  * zlib:x64-windows 1.3.1#2 -> 1.3.2
"""
    )
    assert len(vcpkg_items) == 1
    assert vcpkg_items[0].provider == "vcpkg"
    assert vcpkg_items[0].classification == CLASS_MANUAL_REVIEW
    assert not WinDevPilotApp._item_is_recommended_selectable(vcpkg_items[0])
    assert VcpkgProvider().build_update_command(vcpkg_items[0]) == [
        "vcpkg",
        "upgrade",
        "zlib:x64-windows",
        "--no-dry-run",
    ]
    assert VcpkgProvider().build_uninstall_command(vcpkg_items[0]) == [
        "vcpkg",
        "remove",
        "zlib:x64-windows",
    ]
    npm_fixture_provider = NpmProvider()
    npm_items = npm_fixture_provider._items_from_data(
        {
            "typescript": [
                {"current": "5.0.0", "latest": "5.1.0"},
                {"current": "4.9.0", "latest": "5.1.0"},
            ]
        }
    )
    assert len(npm_items) == 2 and npm_items[0].key != npm_items[1].key
    assert "--loglevel=verbose" in npm_fixture_provider.build_update_command(npm_items[0])
    assert npm_fixture_provider.build_uninstall_command(npm_items[0]) == [
        "npm",
        "uninstall",
        "--global",
        "typescript",
        "--loglevel=verbose",
    ]
    npm_warning_result = CommandResult(
        0,
        "npm warn install-scripts 2 packages had install scripts blocked",
        [],
    )
    npm_warning_entry = command_result_entry(
        npm_items[0],
        npm_fixture_provider,
        npm_warning_result,
        execution_context="self-test",
    )
    assert npm_warning_entry["outcome"] == "updated-with-warnings"
    assert npm_warning_entry["warnings"]
    unsafe_npm = dataclasses.replace(
        item,
        provider="npm",
        package_id="typescript",
        available="1.0 & calc",
        scope="user",
        requires_admin=False,
    )
    assert NpmProvider().update(unsafe_npm).returncode == 2
    bun_fixture_provider = BunProvider()
    bun_items = bun_fixture_provider._items_from_output(
        """
Package        Current  Update   Latest
---------------------------------------
typescript     5.0.0    5.1.0    5.1.0
"""
    )
    assert len(bun_items) == 1
    assert bun_items[0].provider == "bun"
    assert bun_items[0].scope == "user"
    assert BunProvider().build_update_command(bun_items[0]) == [
        "bun",
        "add",
        "--global",
        "--no-progress",
        "typescript@5.1.0",
    ]
    assert BunProvider().build_uninstall_command(bun_items[0]) == [
        "bun",
        "remove",
        "--global",
        "--no-progress",
        "typescript",
    ]
    with tempfile.TemporaryDirectory() as empty_bun_tmp:

        class EmptyGlobalBunProvider(BunProvider):
            @staticmethod
            def _global_package_json() -> Path:
                return Path(empty_bun_tmp) / "missing" / "package.json"

        empty_bun_provider = EmptyGlobalBunProvider()
        assert empty_bun_provider.discover() == []
        assert empty_bun_provider.discover_all() == []
        assert empty_bun_provider.warnings == []
    assert WinDevPilotApp._background_icon_failure_event(
        None,
        "no local icon source was found",
    ) == ("background_icon_source_unavailable", "provider-marker")
    assert WinDevPilotApp._background_icon_failure_event(
        Path("example.exe"),
        "icon format could not be normalized or rendered",
    ) == ("background_icon_prepare_failed", "")
    pip_item = dataclasses.replace(
        item,
        provider="pip",
        package_id="example-package",
        available="2.0",
        scope="user",
        requires_admin=False,
    )
    original_shutil_which_for_pip = shutil.which
    try:
        shutil.which = lambda name: r"C:\Python\python.exe" if name == "python" else None  # type: ignore[assignment]
        assert user_pip_python_prefix() == [r"C:\Python\python.exe"]
        shutil.which = lambda name: sys.executable if name == "python" else None  # type: ignore[assignment]
        try:
            user_pip_python_prefix()
        except FileNotFoundError:
            pass
        else:
            raise AssertionError("pip provider accepted the WinDevPilot runtime Python")
    finally:
        shutil.which = original_shutil_which_for_pip  # type: ignore[assignment]
    # Command/parser fixtures must not require a separately installed Python.
    # Actual interpreter resolution, including app-runtime rejection, is tested above.
    with patch.dict(globals(), user_pip_python_prefix=lambda: ["fixture-python.exe"]):
        pip_command = PipProvider().build_update_command(pip_item)
        pip_uninstall_command = PipProvider().build_uninstall_command(pip_item)
    assert pip_command[0] == "fixture-python.exe"
    assert "--verbose" in pip_command
    assert "--no-input" in pip_command
    assert "--no-color" in pip_command
    assert "--no-cache-dir" in pip_command
    assert pip_uninstall_command[-2:] == ["--verbose", "example-package"]
    assert "uninstall" in pip_uninstall_command and "--yes" in pip_uninstall_command
    original_run_capture_for_pip = globals()["run_capture"]
    pip_discovery_commands: list[list[str]] = []
    try:

        def fake_pip_discovery(command: Sequence[str], **_kwargs: Any) -> CommandResult:
            pip_discovery_commands.append(list(command))
            return CommandResult(
                0,
                '[{"name":"example-package","version":"1.0","latest_version":"2.0"}]',
                [],
            )

        globals()["run_capture"] = fake_pip_discovery
        with patch.dict(globals(), user_pip_python_prefix=lambda: ["fixture-python.exe"]):
            discovered_pip_items = PipProvider().discover()
    finally:
        globals()["run_capture"] = original_run_capture_for_pip
    assert "--user" in pip_discovery_commands[0]
    assert len(discovered_pip_items) == 1
    assert not discovered_pip_items[0].selected
    assert discovered_pip_items[0].source == "pip user site"
    pip_success_with_conflicts = CommandResult(
        0,
        """
Installing collected packages: pyyaml, idna, hf-xet, h11, click, httpcore, anyio, httpx, huggingface_hub
WARNING: The scripts hf.exe, huggingface-cli.exe and tiny-agents.exe are installed in 'C:\\Users\\tester\\AppData\\Roaming\\Python\\Python314\\Scripts' which is not on PATH.
ERROR: pip's dependency resolver does not currently take into account all the packages that are installed. This behaviour is the source of the following dependency conflicts.
semgrep 1.153.1 requires peewee~=3.14, which is not installed.
omegaconf 2.3.0 requires antlr4-python3-runtime==4.9.*, but you have antlr4-python3-runtime 4.13.2 which is incompatible.
Successfully installed anyio-4.14.2 click-8.4.2 h11-0.16.0 hf-xet-1.5.2 httpcore-1.0.9 httpx-0.28.1 huggingface_hub-1.24.0 idna-3.18 pyyaml-6.0.3
""",
        [],
    )
    pip_effects = parse_pip_install_output(pip_success_with_conflicts.output)
    assert pip_effects.successfully_installed["huggingface_hub"] == "1.24.0"
    assert "click" in pip_effects.touched_packages
    assert pip_effects.resolver_conflicts
    assert pip_effects.scripts_not_on_path
    assert pip_effects.has_warnings
    pip_warning_entry = command_result_entry(
        pip_item,
        PipProvider(),
        pip_success_with_conflicts,
        execution_context="self-test",
    )
    assert pip_warning_entry["outcome"] == "updated-with-warnings"
    assert pip_warning_entry["warnings"]
    assert pip_warning_entry["pip_side_effects"]["has_warnings"]
    pip_uninstall_entry = command_result_entry(
        pip_item,
        PipProvider(),
        CommandResult(0, "Successfully uninstalled example-package", []),
        execution_context="self-test",
        operation="uninstall",
    )
    assert pip_uninstall_entry["outcome"] == "uninstalled"
    assert not pip_uninstall_entry["pip_side_effects"]
    assert "dependency warnings" in PipProvider().status_hint(pip_success_with_conflicts)
    assert compare_semantic_versions("2.0.0", "1.9.9") == 1
    assert compare_semantic_versions("1.2.3.0", "1.2.3") == 0
    assert compare_semantic_versions("1.2.3", "1.2.3-rc.1") == 1
    assert compare_semantic_versions("1.2.3-rc.2", "1.2.3-rc.10") == -1
    assert compare_semantic_versions("1.0rc1", "1.0") is None

    class NugetResponseFixture:
        def __init__(self, payload: Any) -> None:
            self.payload = payload

        def __enter__(self) -> NugetResponseFixture:
            return self

        def __exit__(self, *_args: Any) -> None:
            return None

        def read(self, _limit: int) -> bytes:
            return json.dumps(self.payload).encode("utf-8")

    original_urlopen = urllib.request.urlopen
    nuget_payload: Any = {
        "data": [
            {"id": "dotnet-ef-helper", "version": "99.0.0"},
            {"id": "dotnet-ef", "version": "9.0.2"},
        ]
    }
    nuget_requests: list[str] = []
    try:

        def fake_nuget_urlopen(request: Any, *, timeout: int) -> NugetResponseFixture:
            assert timeout == 15
            nuget_requests.append(str(request.full_url))
            return NugetResponseFixture(nuget_payload)

        urllib.request.urlopen = fake_nuget_urlopen
        assert latest_nuget_listed_version("dotnet-ef") == ("9.0.2", "")
        nuget_payload = {"data": [{"id": "dotnet-ef-helper", "version": "99.0.0"}]}
        missing_version, missing_warning = latest_nuget_listed_version("dotnet-ef")
        assert not missing_version
        assert "no unique exact listed package" in missing_warning
        nuget_payload = {"data": [{"id": "dotnet-ef", "version": "unorderable"}]}
        unsafe_version, unsafe_warning = latest_nuget_listed_version("dotnet-ef")
        assert not unsafe_version
        assert "unsafe or unorderable" in unsafe_warning
    finally:
        urllib.request.urlopen = original_urlopen
    assert nuget_requests and "prerelease=false" in nuget_requests[0]

    pipx_fixture_provider = PipxProvider()
    original_latest_pypi = globals()["latest_pypi_version"]
    pypi_lookup_names: list[str] = []
    try:

        def fake_latest_pypi(package_id: str) -> tuple[str, str]:
            pypi_lookup_names.append(package_id)
            return {
                "black": "26.1.0",
                "downgrade-tool": "1.9.0",
                "pinned-tool": "2.0.0",
            }.get(package_id, ""), ""

        globals()["latest_pypi_version"] = fake_latest_pypi
        pipx_items = pipx_fixture_provider._items_from_data(
            {
                "venvs": {
                    "black-cli": {
                        "metadata": {
                            "main_package": {
                                "package": "black",
                                "package_version": "25.1.0",
                            }
                        }
                    },
                    "pinned-tool": {
                        "metadata": {
                            "main_package": {
                                "package": "pinned-tool",
                                "package_version": "1.0.0",
                                "pinned": True,
                            }
                        }
                    },
                    "downgrade-tool": {
                        "metadata": {
                            "main_package": {
                                "package": "downgrade-tool",
                                "package_version": "2.0.0",
                            }
                        }
                    },
                }
            }
        )
    finally:
        globals()["latest_pypi_version"] = original_latest_pypi
    assert len(pipx_items) == 1
    assert pypi_lookup_names == ["black", "downgrade-tool"]
    assert pipx_items[0].package_id == "black-cli"
    assert pipx_items[0].available == "26.1.0"
    assert PipxProvider().build_update_command(pipx_items[0]) == [
        "pipx",
        "upgrade",
        "black-cli",
    ]
    assert PipxProvider().build_uninstall_command(pipx_items[0]) == [
        "pipx",
        "uninstall",
        "black-cli",
    ]
    assert any("pinned" in warning for warning in pipx_fixture_provider.warnings)
    original_pipx_run_capture = globals()["run_capture"]
    original_latest_pypi = globals()["latest_pypi_version"]
    pipx_list_calls = 0
    try:

        def fake_pipx_run_capture(parts: Sequence[str], **_kwargs: Any) -> CommandResult:
            nonlocal pipx_list_calls
            assert list(parts) == ["pipx", "list", "--json"]
            pipx_list_calls += 1
            return CommandResult(
                0,
                json.dumps(
                    {
                        "venvs": {
                            "black-cli": {
                                "metadata": {
                                    "main_package": {
                                        "package": "black",
                                        "package_version": "25.1.0",
                                    }
                                }
                            }
                        }
                    }
                ),
                list(parts),
            )

        globals()["run_capture"] = fake_pipx_run_capture
        globals()["latest_pypi_version"] = lambda _package_id: ("26.1.0", "")
        cached_pipx_provider = PipxProvider()
        assert len(cached_pipx_provider.discover()) == 1
        assert len(cached_pipx_provider.discover_all()) == 1
    finally:
        globals()["run_capture"] = original_pipx_run_capture
        globals()["latest_pypi_version"] = original_latest_pypi
    assert pipx_list_calls == 1
    dotnet_rows = DotNetToolProvider._parse_tool_list(
        """
Package Id      Version      Commands
-------------------------------------
dotnet-ef       9.0.1        dotnet-ef
bad row
"""
    )
    assert dotnet_rows == [{"id": "dotnet-ef", "version": "9.0.1"}]
    original_dotnet_run_capture = globals()["run_capture"]
    original_latest_nuget = globals()["latest_nuget_listed_version"]
    dotnet_list_calls = 0
    try:

        def fake_dotnet_run_capture(parts: Sequence[str], **_kwargs: Any) -> CommandResult:
            nonlocal dotnet_list_calls
            assert list(parts) == ["dotnet", "tool", "list", "--global"]
            dotnet_list_calls += 1
            return CommandResult(
                0,
                "Package Id      Version      Commands\n"
                "-------------------------------------\n"
                "dotnet-ef       9.0.1        dotnet-ef\n",
                list(parts),
            )

        globals()["run_capture"] = fake_dotnet_run_capture
        globals()["latest_nuget_listed_version"] = lambda _package_id: ("9.0.2", "")
        dotnet_fixture_provider = DotNetToolProvider()
        dotnet_updates = dotnet_fixture_provider.discover()
        dotnet_installed = dotnet_fixture_provider.discover_all()
    finally:
        globals()["run_capture"] = original_dotnet_run_capture
        globals()["latest_nuget_listed_version"] = original_latest_nuget
    assert dotnet_list_calls == 1
    assert len(dotnet_updates) == len(dotnet_installed) == 1
    assert dotnet_updates[0].available == "9.0.2"
    dotnet_item = dataclasses.replace(
        item,
        provider="dotnet-tool",
        package_id="dotnet-ef",
        available="9.0.2",
        scope="user",
        requires_admin=False,
    )
    assert DotNetToolProvider().build_update_command(dotnet_item) == [
        "dotnet",
        "tool",
        "update",
        "dotnet-ef",
        "--global",
        "--version",
        "9.0.2",
    ]
    assert DotNetToolProvider().build_uninstall_command(dotnet_item) == [
        "dotnet",
        "tool",
        "uninstall",
        "dotnet-ef",
        "--global",
    ]
    uv_items = UvToolProvider()._items_from_outdated_output(
        """
ruff v0.13.0 [latest: 0.13.2]
- ruff
"""
    )
    assert len(uv_items) == 1
    assert uv_items[0].package_id == "ruff"
    assert uv_items[0].available == "0.13.2"
    assert UvToolProvider().build_update_command(uv_items[0]) == [
        "uv",
        "--color",
        "never",
        "tool",
        "upgrade",
        "ruff",
    ]
    assert UvToolProvider().build_uninstall_command(uv_items[0]) == [
        "uv",
        "--color",
        "never",
        "tool",
        "uninstall",
        "ruff",
    ]
    assert "Example.Module" in render_ps5_module_update_script(
        "Example.Module", "1.2.3", "PSGallery"
    )
    powershell_literal_rejected = False
    try:
        require_powershell_single_quoted_literals("Example.Module' ; Write-Output unsafe")
    except ValueError:
        powershell_literal_rejected = True
    assert powershell_literal_rejected
    powershell_uninstall_rejected = False
    try:
        render_ps5_module_uninstall_script("Example.Module'", "1.2.3")
    except ValueError:
        powershell_uninstall_rejected = True
    assert powershell_uninstall_rejected
    combined_powershell_calls: list[list[str]] = []

    def fake_combined_powershell_discovery(
        command: list[str], *_args: Any, **_kwargs: Any
    ) -> CommandResult:
        combined_powershell_calls.append(command)
        if command[0] == "pwsh":
            begin, end = PSRESOURCE_JSON_BEGIN, PSRESOURCE_JSON_END
            combined_payload = {
                "Schema": 2,
                "Updates": {
                    "Schema": 1,
                    "Warnings": [],
                    "Items": [
                        {
                            "Name": "Example.Resource",
                            "Current": "1.0.0",
                            "Available": "1.1.0",
                            "Repository": "PSGallery",
                            "InstalledVersions": ["1.0.0"],
                        }
                    ],
                },
                "Installed": {
                    "Schema": 1,
                    "Warnings": [],
                    "Items": [
                        {
                            "Name": "Example.Resource",
                            "Version": "1.0.0",
                            "Repository": "PSGallery",
                            "Type": "Module",
                            "Location": r"C:\Users\fixture\Documents\PowerShell\Modules",
                        }
                    ],
                },
            }
        else:
            begin, end = PS5_MODULE_JSON_BEGIN, PS5_MODULE_JSON_END
            combined_payload = {
                "Schema": 2,
                "Updates": {
                    "Schema": 1,
                    "Warnings": [],
                    "Items": [
                        {
                            "Name": "Pester",
                            "Current": "5.6.0",
                            "Available": "5.7.1",
                            "Repository": "PSGallery",
                        }
                    ],
                },
                "Installed": {
                    "Schema": 1,
                    "Warnings": [],
                    "Items": [
                        {
                            "Name": "Pester",
                            "Version": "5.6.0",
                            "Repository": "PSGallery",
                            "Location": (
                                r"C:\Users\fixture\Documents\WindowsPowerShell\Modules"
                            ),
                        }
                    ],
                },
            }
        output = f"{begin}\n{json.dumps(combined_payload)}\n{end}\n"
        return CommandResult(returncode=0, output=output, command=command)

    saved_powershell_run_capture = globals()["run_capture"]
    try:
        globals()["run_capture"] = fake_combined_powershell_discovery
        combined_ps7_provider = PowerShellProvider()
        assert len(combined_ps7_provider.discover()) == 1
        assert len(combined_ps7_provider.discover_all()) == 1
        combined_ps5_provider = WindowsPowerShellProvider()
        assert len(combined_ps5_provider.discover()) == 1
        assert len(combined_ps5_provider.discover_all()) == 1
    finally:
        globals()["run_capture"] = saved_powershell_run_capture
    assert [command[0] for command in combined_powershell_calls] == ["pwsh", "powershell"]
    powershell_fixture_provider = PowerShellProvider()
    powershell_items = powershell_fixture_provider._items_from_payload(
        {
            "Schema": 1,
            "Warnings": ["fixture repository warning"],
            "Items": [
                {
                    "Name": "Example.Resource",
                    "Current": "1.0.0",
                    "Available": "1.1.0-preview.1",
                    "Repository": "PSGallery",
                    "Type": "Module",
                    "InstalledLocation": r"C:\Users\fixture\Modules\Example.Resource",
                    "InstalledVersions": ["1.0.0", "0.9.0"],
                },
                {
                    "Name": "Unsafe.Resource",
                    "Current": "1.0.0",
                    "Available": "2.0.0",
                    "Repository": "https://example.invalid/api",
                    "InstalledVersions": ["1.0.0"],
                },
            ],
        }
    )
    assert len(powershell_items) == 1
    assert powershell_items[0].scope == "user"
    assert not powershell_items[0].requires_admin
    assert powershell_items[0].source == "PSGallery"
    assert any(
        "fixture repository warning" in warning for warning in powershell_fixture_provider.warnings
    )
    assert any(
        "2 CurrentUser versions" in warning for warning in powershell_fixture_provider.warnings
    )
    assert any("unsafe repository" in warning for warning in powershell_fixture_provider.warnings)
    powershell_command = powershell_fixture_provider.build_update_command(powershell_items[0])
    assert "-CommandWithArgs" in powershell_command
    assert powershell_command[-3:] == [
        "Example.Resource",
        "1.1.0-preview.1",
        "PSGallery",
    ]
    assert "Example.Resource" not in PSRESOURCE_UPDATE_SCRIPT
    assert "ExecutionPolicy" not in PSRESOURCE_UPDATE_SCRIPT
    assert "Force" not in PSRESOURCE_UPDATE_SCRIPT
    assert "CurrentUser" in PSRESOURCE_UPDATE_SCRIPT
    assert "Prerelease" in PSRESOURCE_UPDATE_SCRIPT
    powershell_uninstall = powershell_fixture_provider.build_uninstall_command(powershell_items[0])
    assert "Uninstall-PSResource" in powershell_uninstall[-3]
    assert powershell_uninstall[-2:] == ["Example.Resource", "1.0.0"]
    powershell5_fixture_provider = WindowsPowerShellProvider()
    powershell5_items = powershell5_fixture_provider._items_from_payload(
        {
            "Schema": 1,
            "Warnings": [
                "1 Windows PowerShell module(s) installed outside CurrentUser were skipped"
            ],
            "Items": [
                {
                    "Name": "Pester",
                    "Current": "5.6.0",
                    "Available": "5.7.1",
                    "Repository": "PSGallery",
                    "InstalledLocation": r"C:\Users\fixture\Documents\WindowsPowerShell\Modules\Pester\5.6.0",
                }
            ],
        }
    )
    assert len(powershell5_items) == 1
    assert powershell5_items[0].provider == "powershell5"
    assert powershell5_items[0].scope == "user"
    assert any(
        "outside CurrentUser" in warning for warning in powershell5_fixture_provider.warnings
    )
    powershell5_command = powershell5_fixture_provider.build_update_command(powershell5_items[0])
    assert powershell5_command[:4] == [
        "powershell",
        "-NoLogo",
        "-NoProfile",
        "-NonInteractive",
    ]
    assert powershell5_command[-2] == "-Command"
    assert "$args" not in powershell5_command[-1]
    assert "$name = 'Pester'" in powershell5_command[-1]
    assert "$version = '5.7.1'" in powershell5_command[-1]
    assert "$repository = 'PSGallery'" in powershell5_command[-1]
    assert "GetFolderPath('MyDocuments')" in PS5_MODULE_DISCOVERY_SCRIPT
    assert "GetFolderPath('MyDocuments')" in PS5_MODULE_UPDATE_SCRIPT
    assert "Scope = 'CurrentUser'" in PS5_MODULE_UPDATE_SCRIPT
    assert "RequiredVersion" in PS5_MODULE_UPDATE_SCRIPT
    if os.name == "nt":
        # Run only a local parameter-binding double, never Install-Module itself.
        binding_fixture = r"""
function Invoke-WdpFixtureInstall {
    [CmdletBinding(SupportsShouldProcess=$true)]
    param([string]$Name, [string]$RequiredVersion, [string]$Repository,
          [string]$Scope, [switch]$Force, [switch]$AllowClobber{LICENSE_PARAMETER})
    [pscustomobject]@{
        Name=$Name; Version=$RequiredVersion; Repository=$Repository; Scope=$Scope
        AcceptLicense=$PSBoundParameters.ContainsKey('AcceptLicense')
        Force=[bool]$Force; AllowClobber=[bool]$AllowClobber
        Confirm=[bool]$PSBoundParameters['Confirm']
    } | ConvertTo-Json -Compress
}
function Import-Module { [CmdletBinding()] param([string]$Name) }
function Get-Command {
    [CmdletBinding()] param([string]$Name)
    if ($Name -ne 'PowerShellGet\Install-Module') { throw 'Unexpected command lookup' }
    Microsoft.PowerShell.Core\Get-Command Invoke-WdpFixtureInstall
}
"""
        for accepts_license in (False, True):
            binding_script = binding_fixture.replace(
                "{LICENSE_PARAMETER}", ", [switch]$AcceptLicense" if accepts_license else "",
            ) + render_ps5_module_update_script("Example.Module", "1.2.3", "PSGallery")
            bound_result = run_capture(
                ["powershell", "-NoLogo", "-NoProfile", "-NonInteractive", "-Command", binding_script],
                timeout=20,
            )
            assert bound_result.returncode == 0, bound_result.output
            assert json.loads(bound_result.output) == {
                "Name": "Example.Module", "Version": "1.2.3", "Repository": "PSGallery",
                "Scope": "CurrentUser", "AcceptLicense": accepts_license,
                "Force": True, "AllowClobber": True, "Confirm": False,
            }
    assert (
        strip_display_icon_index(r"C:\Program Files\Example App\Example.exe")
        == r"C:\Program Files\Example App\Example.exe"
    )
    assert (
        strip_display_icon_index(r"C:\Program Files\Example App\Example.exe,0")
        == r"C:\Program Files\Example App\Example.exe"
    )
    powershell5_uninstall = powershell5_fixture_provider.build_uninstall_command(
        powershell5_items[0]
    )
    assert "Uninstall-Module" in powershell5_uninstall[-1]
    assert "-RequiredVersion '5.6.0'" in powershell5_uninstall[-1]
    unsafe_powershell = dataclasses.replace(powershell_items[0], source="PSGallery; Remove-Item")
    assert PowerShellProvider().update(unsafe_powershell).returncode == 2
    elevated_powershell = dataclasses.replace(
        powershell_items[0], scope="machine", requires_admin=True
    )
    try:
        validate_elevation_payload(
            {"schema": 1, "items": [elevated_powershell.to_plan_dict()]},
            elevation_providers,
        )
    except ValueError:
        pass
    else:
        raise AssertionError("a PowerShell resource crossed the elevation boundary")
    with tempfile.TemporaryDirectory(prefix="WinDevPilot-self-test-") as temp_dir:
        test_dir = Path(temp_dir)
        atomic_fixture = test_dir / "atomic.json"
        atomic_write_text(atomic_fixture, '{"schema": 1}')
        assert atomic_fixture.read_text(encoding="utf-8") == '{"schema": 1}'
        if os.name == "nt":
            retry_delays: list[float] = []
            replace_attempts = 0

            def transient_replace(source: Path, target: Path) -> None:
                nonlocal replace_attempts
                replace_attempts += 1
                if replace_attempts < 3:
                    raise ctypes.WinError(32 if replace_attempts == 1 else 5)
                os.replace(source, target)

            retry_source = test_dir / "retry-source.json"
            retry_target = test_dir / "retry-target.json"
            retry_source.write_text('{"retried": true}', encoding="utf-8")
            _replace_file_with_windows_retry(
                retry_source,
                retry_target,
                replace=transient_replace,
                pause=retry_delays.append,
            )
            assert replace_attempts == 3
            assert retry_delays == list(ATOMIC_REPLACE_RETRY_DELAYS_SECONDS[:2])
            assert retry_target.read_text(encoding="utf-8") == '{"retried": true}'

            permanent_source = test_dir / "permanent-source.json"
            permanent_source.write_text("unchanged", encoding="utf-8")
            permanent_delays: list[float] = []

            def permanent_replace(_source: Path, _target: Path) -> None:
                raise PermissionError("permanent test failure")

            try:
                _replace_file_with_windows_retry(
                    permanent_source,
                    retry_target,
                    replace=permanent_replace,
                    pause=permanent_delays.append,
                )
            except PermissionError:
                pass
            else:
                raise AssertionError("atomic replacement retried a permanent failure")
            assert not permanent_delays
        try:
            atomic_write_text(atomic_fixture, "too large", max_bytes=3)
        except ValueError:
            pass
        else:
            raise AssertionError("atomic writer accepted content above its size limit")
        assert atomic_fixture.read_text(encoding="utf-8") == '{"schema": 1}'
        report_rows = [
            (
                "Example\tApp",
                "Example.App",
                "1.0.0",
                "≈ 2026-08-30",
                "WinGet",
                "Current account",
                "",
                system_report_path_text(r"C:\Program Files\Example App"),
                "exe",
                "1.0 GB",
            )
        ]
        report_path = write_system_report(
            test_dir / "system-report.txt",
            report_rows,
            provisional_count=1,
            generated_at=dt.datetime(
                2026, 8, 30, 12, 34, 56, 654321, tzinfo=dt.UTC
            ),
        )
        report_text = report_path.read_text(encoding="utf-8")
        assert report_text.startswith("WinDevPilot system report\n")
        assert "Generated: 2026-08-30T12:34:56.65+00:00" in report_text
        assert "System: Windows build" in report_text
        assert "Inventory freshness: 0 current, 1 from previous inventory" in report_text
        assert "This report contains" not in report_text
        assert "Name: Example\tApp" in report_text
        assert "Available:" not in report_text
        assert "Status:" not in report_text
        assert '#1\nName: Example\tApp' in report_text
        assert "Package 1 of 1" not in report_text
        assert "--------------------------------" not in report_text
        assert r'Installed folder: "C:\Program Files\Example App"' in report_text
        assert "Metadata (JSON):" not in report_text
        assert "Installed technology: exe    Installed size: 1.0 GB" in report_text
        update_report_row = list(report_rows[0])
        update_report_row[6] = "Update available — 1.1.0"
        update_report_text = system_report_text(
            [update_report_row],
            generated_at=dt.datetime(2026, 8, 30, tzinfo=dt.UTC),
            system_build=26200,
            system_architecture="AMD64",
        )
        assert "System: Windows build 26200; architecture: AMD64" in update_report_text
        assert "Available:" not in update_report_text
        assert "Status: Update available — 1.1.0" in update_report_text
        sparse_report_row = list(report_rows[0])
        sparse_report_row[3] = ""
        sparse_report_row[7] = ""
        sparse_report_row[8] = ""
        sparse_report_row[9] = ""
        sparse_report_text = system_report_text([sparse_report_row])
        assert "Installed / serviced:" not in sparse_report_text
        assert "Installed folder:" not in sparse_report_text
        assert "Installed technology:" not in sparse_report_text
        assert "Installed size:" not in sparse_report_text
        technology_only_report = system_report_text(
            [(*report_rows[0][:-2], "msi", "")],
            generated_at=dt.datetime(2026, 8, 30, tzinfo=dt.UTC),
        )
        assert "Installed technology: msi\n" in technology_only_report
        assert "Installed size:" not in technology_only_report
        assert system_report_path_text(r'C:\Program Files\Quoted App') == (
            r'"C:\Program Files\Quoted App"'
        )
        assert system_report_path_text(r'"C:\Program Files\Quoted App"') == (
            r'"C:\Program Files\Quoted App"'
        )
        assert system_report_path_text(r'"C:\Program Files\Quoted App\"') == (
            r'"C:\Program Files\Quoted App"'
        )
        assert system_report_path_text(r"C:\Tools\Example") == r"C:\Tools\Example"
        assert system_report_path_text("") == ""
        report_cap_path = test_dir / "system-report-over-limit.txt"
        saved_report_limit = globals()["SYSTEM_REPORT_MAX_BYTES"]
        globals()["SYSTEM_REPORT_MAX_BYTES"] = 8
        try:
            try:
                write_system_report(report_cap_path, report_rows)
            except ValueError:
                pass
            else:
                raise AssertionError("system report exceeded its size limit")
        finally:
            globals()["SYSTEM_REPORT_MAX_BYTES"] = saved_report_limit
        assert not report_cap_path.exists()
        report_probe = object.__new__(WinDevPilotApp)
        report_probe.settings = type("ReportSettingsFixture", (), {"data": {}})()
        report_probe.busy = False
        report_probe._scan_active = False
        report_item = UpdateItem(
            provider="winget",
            name="Full ID example",
            package_id="Example.Full.Package.Identity",
            current="2.0.0",
            available="2.0.0",
            source="winget",
            status="Installed",
            classification=CLASS_INVENTORY_ONLY,
            installed_for="machine",
            installed_technology="exe",
            installed_location=r"C:\Program Files\Full ID Example",
            installed_size_kb=1536,
            installed_date_source="Windows uninstall InstallDate",
            metadata_sources=("arp-uninstall",),
            metadata_confidence="proven",
            publisher="Example Publisher",
            architecture="x64",
        )
        report_update_item = dataclasses.replace(
            report_item,
            available="2.1.0",
            status="Ready",
            classification=CLASS_SIMPLE_UPGRADE,
        )
        assert system_report_update_version(report_item, [report_update_item]) == "2.1.0"
        assert (
            system_report_update_version(
                report_item,
                [report_update_item, dataclasses.replace(report_update_item, available="2.2.0")],
            )
            == ""
        )
        assert (
            system_report_update_version(
                report_item,
                [dataclasses.replace(report_update_item, available=report_item.current)],
            )
            == ""
        )
        report_probe._scan_view_items = {
            False: {report_update_item.key: report_update_item},
            True: {report_item.key: report_item},
        }
        report_probe.providers = {
            "winget": type("ReportProviderProbe", (), {"label": "WinGet"})()
        }
        report_probe._item_row_values = lambda _item: (
            "",
            "Full ID example",
            "Example…Identity",
            "2.0.0",
            "2.0.0",
            "2026-08-30",
            "WinGet",
            "Installed",
        )
        report_probe._item_inventory_is_provisional = lambda _item: False
        report_probe.process_is_admin = False
        dialog_calls: list[dict[str, Any]] = []
        saved_report_path = test_dir / "saved-through-dialog.txt"

        class ReportFileDialogProbe:
            @staticmethod
            def asksaveasfilename(**kwargs: Any) -> str:
                dialog_calls.append(kwargs)
                return str(saved_report_path)

        report_probe.filedialog = ReportFileDialogProbe()
        report_probe.root = object()
        report_events: list[tuple[str, dict[str, Any]]] = []
        report_probe.logger = type(
            "ReportLoggerProbe",
            (),
            {"event": lambda _self, name, **fields: report_events.append((name, fields))},
        )()
        report_notifications: list[tuple[str, dict[str, Any]]] = []
        report_probe._notify_user = lambda message, **fields: report_notifications.append(
            (message, fields)
        )
        report_probe.save_system_report()
        assert dialog_calls[0]["defaultextension"] == ".txt"
        assert dialog_calls[0]["title"] == "Save WinDevPilot system report"
        saved_report_text = saved_report_path.read_text(encoding="utf-8")
        assert "ID: Example.Full.Package.Identity" in saved_report_text
        assert "Example…Identity" not in saved_report_text
        assert (
            r'Installed folder: "C:\Program Files\Full ID Example"'
            in saved_report_text
        )
        assert "Metadata (JSON):" not in saved_report_text
        assert "Example Publisher" not in saved_report_text
        assert "Available:" not in saved_report_text
        assert "Status: Update available — 2.1.0" in saved_report_text
        assert "Run as: Current account" in saved_report_text
        assert "Installed technology: exe    Installed size: 1.5 MB" in saved_report_text
        assert report_events[0][0] == "system_report_saved"
        assert report_notifications[0][1]["level"] == "success"
        report_probe.settings.data = {"package_history": remember_package_history_event(
            {}, provider=report_item.provider, package_id=report_item.package_id,
            name=report_item.name, action="update", observed_at=service_time.isoformat(),
            version=report_item.current, scope=report_item.scope, source=report_item.source,
        )}
        report_probe.save_system_report()
        saved_report_text = saved_report_path.read_text(encoding="utf-8")
        assert (
            "Installed / serviced: "
            + local_observation_time(service_time.isoformat())
            + " — Updated by WinDevPilot (verified)"
            in saved_report_text
        )
        gallery_fixture = test_dir / "gallery"
        gallery_fixture.mkdir()
        gallery_rows = [bytes((15, 120, 210, 255)) * 12 for _ in range(12)]
        for gallery_name in ("small.png", "large.png"):
            write_rgba_png(gallery_fixture / gallery_name, 12, 12, gallery_rows)
        gallery_payload = {
            "items": [
                {
                    "path": gallery_name,
                    "width": 12,
                    "height": 12,
                    "sources": [gallery_name],
                    "retrievals": ["self-test"],
                    "checkerboard": False,
                }
                for gallery_name in ("small.png", "large.png")
            ]
        }
        gallery_bundle = pack_icon_gallery_memory(gallery_fixture, gallery_payload)
        assert gallery_bundle.raw_size == len(gallery_bundle.payload)
        assert gallery_bundle.item_count == 2
        gallery_wire = serialize_icon_gallery_bundle(gallery_bundle)
        gallery_bundle = deserialize_icon_gallery_bundle(gallery_wire)
        unpacked_gallery = gallery_bundle.unpack()
        assert [record["filename"] for record, _image in unpacked_gallery] == [
            "small.png",
            "large.png",
        ]
        assert all(image.startswith(b"\x89PNG\r\n\x1a\n") for _record, image in unpacked_gallery)
        details_png = rgba_png_bytes(12, 12, gallery_rows)
        with_details = append_package_details_rendition(
            unpacked_gallery,
            details_png,
            str(gallery_fixture / "source.exe"),
        )
        assert len(with_details) == 2
        assert any(
            record.get("package_details_rendition")
            and "WinDevPilot Package Details rendition" in record["retrievals"]
            for record, _png_data in with_details
        )
        distinct_details_rows = [
            bytes((210, 80, 25, 255)) * 12 for _ in range(12)
        ]
        with_distinct_details = append_package_details_rendition(
            unpacked_gallery,
            rgba_png_bytes(12, 12, distinct_details_rows),
            str(gallery_fixture / "source.exe"),
        )
        assert len(with_distinct_details) == 3
        assert with_distinct_details[-1][0]["package_details_rendition"]
        try:
            deserialize_icon_gallery_bundle(gallery_wire[:-1])
        except ValueError:
            pass
        else:
            raise AssertionError("truncated raw-memory gallery was accepted")
        desktop_ini_fixture = test_dir / "desktop-icon"
        desktop_ini_fixture.mkdir()
        desktop_icon_fixture = desktop_ini_fixture / "folder-app.ico"
        desktop_icon_fixture.write_bytes(b"fixture")
        (desktop_ini_fixture / "desktop.ini").write_text(
            "[.ShellClassInfo]\nIconResource=folder-app.ico,0\n",
            encoding="utf-16",
        )
        assert desktop_ini_icon_path(desktop_ini_fixture) == desktop_icon_fixture
        assert install_location_icon_path(str(desktop_ini_fixture), "unmatched app") == (
            desktop_icon_fixture
        )
        (desktop_ini_fixture / "desktop.ini").write_text(
            "[.ShellClassInfo]\nIconFile=folder-app.ico\n",
            encoding=locale.getpreferredencoding(False),
        )
        assert desktop_ini_icon_path(desktop_ini_fixture) == desktop_icon_fixture
        command_fixture = test_dir / "Product Uninstall.exe"
        command_fixture.write_bytes(b"fixture")
        assert local_executable_from_command(f'"{command_fixture}" --remove') == str(
            command_fixture
        )
        alias_fixture = test_dir / "portable-alias"
        alias_fixture.mkdir()
        alias_executable = alias_fixture / "fd.exe"
        alias_executable.write_bytes(b"fixture")
        assert install_location_icon_path(
            str(alias_fixture), "fd", "sharkdp.fd"
        ) == alias_executable
        appx_fixture_dir = test_dir / "appx-assets"
        appx_fixture_dir.mkdir()

        def write_png_header_fixture(path: Path, width: int, height: int) -> None:
            path.write_bytes(
                PNG_SIGNATURE + struct.pack(">I", 13) + b"IHDR" + struct.pack(">II", width, height)
            )

        appx_variants = []
        for scale, dimension in ((50, 120), (100, 310), (200, 620), (400, 1240)):
            path = appx_fixture_dir / f"LargeTile.scale-{scale}.png"
            write_png_header_fixture(path, dimension, dimension)
            appx_variants.append(path)

        def best_appx_variant(target_size: int) -> Path:
            return max(appx_variants, key=lambda path: _appx_asset_score(path, target_size))

        assert best_appx_variant(144).name == "LargeTile.scale-100.png"
        assert best_appx_variant(384).name == "LargeTile.scale-200.png"
        assert best_appx_variant(800).name == "LargeTile.scale-400.png"
        assert best_appx_variant(1600).name == "LargeTile.scale-400.png"
        dimension_cache_hits = _appx_asset_dimensions_cached.cache_info().hits
        assert _appx_asset_dimensions(appx_variants[0]) == (120, 120)
        assert _appx_asset_dimensions_cached.cache_info().hits > dimension_cache_hits
        assert (
            max(
                appx_variants,
                key=lambda path: _appx_asset_score(path, 144, nominal_size=310),
            ).name
            == "LargeTile.scale-50.png"
        )
        blank_tile = appx_fixture_dir / "Square150x150Logo.png"
        detailed_logo = appx_fixture_dir / "AppLogo.targetsize-64.png"
        contrast_logo = appx_fixture_dir / "AppLogo.targetsize-64_contrast-white.png"
        assert _appx_asset_score(detailed_logo, 144) > _appx_asset_score(contrast_logo, 144)
        qualified_logo = appx_fixture_dir / "AppLogo.targetsize-256_altform-unplated.png"
        small_logo = appx_fixture_dir / "AppLogo.targetsize-24.png"
        black_logo = appx_fixture_dir / "AppLogo.targetsize-256_contrast-black.png"
        white_logo = appx_fixture_dir / "AppLogo.targetsize-256_contrast-white.png"
        for path, size in (
            (qualified_logo, 256),
            (small_logo, 24),
            (black_logo, 256),
            (white_logo, 256),
        ):
            write_png_header_fixture(path, size, size)
        qualified_variants = _appx_asset_variants(qualified_logo)
        assert small_logo in qualified_variants
        assert black_logo in qualified_variants
        gallery_sample = _appx_gallery_variant_sample(qualified_logo, qualified_variants)
        assert gallery_sample[0] == qualified_logo
        assert small_logo in gallery_sample
        assert black_logo in gallery_sample
        assert white_logo in gallery_sample
        write_rgba_png(
            blank_tile,
            150,
            150,
            [bytes((255, 255, 255, 255)) * 150 for _ in range(150)],
        )
        write_rgba_png(
            detailed_logo,
            64,
            64,
            [bytes((245, 210, 25, 255)) * 32 + bytes((15, 45, 120, 255)) * 32 for _ in range(64)],
        )
        appx_logo_candidates = [
            (2, _appx_asset_score(blank_tile, 144, nominal_size=150), blank_tile),
            (1, _appx_asset_score(detailed_logo, 144, nominal_size=44), detailed_logo),
        ]
        assert _best_appx_logo_candidate(appx_logo_candidates) == detailed_logo
        unplated_logo = appx_fixture_dir / "AppLogo.targetsize-64_altform-unplated.png"
        write_rgba_png(
            unplated_logo,
            64,
            64,
            [
                b"".join(
                    bytes((255, 255, 255, 255))
                    if 10 <= x <= 53 and 10 <= y <= 53
                    else bytes((0, 0, 0, 0))
                    for x in range(64)
                )
                for y in range(64)
            ],
        )
        assert icon_png_has_visual_detail(unplated_logo)
        assert (
            _best_appx_logo_candidate(
                [
                    (
                        3,
                        _appx_asset_score(detailed_logo, 144, nominal_size=310),
                        detailed_logo,
                    ),
                    (
                        1,
                        _appx_asset_score(unplated_logo, 144, nominal_size=44),
                        unplated_logo,
                    ),
                ]
            )
            == unplated_logo
        )
        target_sized_tile = appx_fixture_dir / "Square150x150Logo.scale-100.png"
        write_rgba_png(
            target_sized_tile,
            150,
            150,
            [
                bytes((25, 80, 180, 255)) * 75 + bytes((245, 205, 35, 255)) * 75
                for _ in range(150)
            ],
        )
        assert (
            _best_appx_logo_candidate(
                [
                    (
                        2,
                        _appx_asset_score(target_sized_tile, 144, nominal_size=150),
                        target_sized_tile,
                    ),
                    (
                        1,
                        _appx_asset_score(unplated_logo, 144, nominal_size=44),
                        unplated_logo,
                    ),
                ]
            )
            == target_sized_tile
        )
        high_dpi_default = appx_fixture_dir / "StoreLogo.scale-600.png"
        write_rgba_png(
            high_dpi_default,
            300,
            300,
            [
                bytes((20, 100, 210, 255)) * 150 + bytes((245, 215, 45, 255)) * 150
                for _ in range(300)
            ],
        )
        assert (
            _best_appx_logo_candidate(
                [
                    (
                        1,
                        _appx_asset_score(qualified_logo, 384, nominal_size=0),
                        qualified_logo,
                    ),
                    (
                        1,
                        _appx_asset_score(high_dpi_default, 384, nominal_size=0),
                        high_dpi_default,
                    ),
                ]
            )
            == high_dpi_default
        )
        assert _icon_frame_score(256, 256, 32, 10_000, 144) > _icon_frame_score(
            512, 512, 32, 20_000, 144
        )
        assert _icon_frame_score(512, 512, 32, 20_000, 300) > _icon_frame_score(
            256, 256, 32, 10_000, 300
        )
        assert _icon_frame_score(512, 512, 32, 20_000, 800) > _icon_frame_score(
            256, 256, 32, 10_000, 800
        )

        ico_payloads = [PNG_SIGNATURE + marker for marker in (b"48", b"128", b"256")]
        ico_header_size = 6 + len(ico_payloads) * 16
        ico_offsets: list[int] = []
        ico_cursor = ico_header_size
        for payload in ico_payloads:
            ico_offsets.append(ico_cursor)
            ico_cursor += len(payload)
        ico_data = bytearray(struct.pack("<HHH", 0, 1, len(ico_payloads)))
        for dimension, payload, offset in zip(
            (48, 128, 256), ico_payloads, ico_offsets, strict=True
        ):
            encoded_dimension = 0 if dimension == 256 else dimension
            ico_data.extend(
                struct.pack(
                    "<BBBBHHII",
                    encoded_dimension,
                    encoded_dimension,
                    0,
                    0,
                    1,
                    32,
                    len(payload),
                    offset,
                )
            )
        ico_data.extend(b"".join(ico_payloads))
        assert [(frame.width, frame.height) for frame in _ico_frames(bytes(ico_data))] == [
            (48, 48),
            (128, 128),
            (256, 256),
        ]
        selected_ico_frame = _best_ico_frame(bytes(ico_data), 100)
        assert selected_ico_frame is not None
        assert (selected_ico_frame.width, selected_ico_frame.height) == (128, 128)
        assert _best_png_frame_from_ico(bytes(ico_data), 40) == ico_payloads[0]
        assert _best_png_frame_from_ico(bytes(ico_data), 100) == ico_payloads[1]
        assert _best_png_frame_from_ico(bytes(ico_data), 144) == ico_payloads[2]
        assert _best_png_frame_from_ico(bytes(ico_data), 512) == ico_payloads[2]
        class SliceCountingIco(bytes):
            def __new__(cls, value: bytes) -> Any:
                instance = super().__new__(cls, value)
                instance.slices = []
                return instance

            def __getitem__(self, index: Any) -> Any:
                if isinstance(index, slice):
                    self.slices.append(index)
                return super().__getitem__(index)

        shared_ico_payload = PNG_SIGNATURE + b"x" * (65536 - len(PNG_SIGNATURE))
        for entry_count in (1, 32, 512):
            shared_offset = 6 + entry_count * 16
            repeated_ico = SliceCountingIco(
                struct.pack("<HHH", 0, 1, entry_count)
                + struct.pack("<BBBBHHII", 32, 32, 0, 0, 1, 32,
                              len(shared_ico_payload), shared_offset) * entry_count
                + shared_ico_payload
            )
            repeated_frames = _ico_frames(repeated_ico)
            assert len(repeated_frames) == entry_count
            assert not repeated_ico.slices, "ICO directory parsing copied frame bytes"
            assert all(not hasattr(frame, "payload") for frame in repeated_frames)
            assert _best_ico_frame(repeated_ico, 32) == repeated_frames[0]
            assert not repeated_ico.slices, "ICO dimension selection copied frame bytes"
            assert _best_png_frame_from_ico(repeated_ico, 32) == shared_ico_payload
            assert len(repeated_ico.slices) == 1, "copy only the selected PNG frame"
        # Ranges may share bytes, but selection must respect each declared end.
        overlap_ico = SliceCountingIco(
            struct.pack("<HHH", 0, 1, 2)
            + struct.pack("<BBBBHHII", 32, 32, 0, 0, 1, 32, len(shared_ico_payload), 38)
            + struct.pack("<BBBBHHII", 64, 64, 0, 0, 1, 32, len(shared_ico_payload) - 1, 39)
            + shared_ico_payload
        )
        assert len(_ico_frames(overlap_ico)) == 2 and not overlap_ico.slices
        assert _best_png_frame_from_ico(overlap_ico, 64) == shared_ico_payload
        assert len(overlap_ico.slices) == 1
        short_png_ico = (
            struct.pack("<HHH", 0, 1, 1)
            + struct.pack("<BBBBHHII", 32, 32, 0, 0, 1, 32, 1, 22)
            + PNG_SIGNATURE
        )
        assert _best_png_frame_from_ico(short_png_ico, 32) is None
        for short_directory_length in range(6 + 3 * 16):
            assert not _ico_frames(bytes(ico_data[:short_directory_length]))
        import random

        ico_rng = random.Random(20260902)
        for _case in range(384):
            mutated_ico = bytearray(ico_data)
            for _change in range(ico_rng.randint(1, 6)):
                mutated_ico[ico_rng.randrange(len(mutated_ico))] = ico_rng.randrange(256)
            if ico_rng.randrange(3) == 0:
                del mutated_ico[ico_rng.randrange(len(mutated_ico)):]
            trial_ico = SliceCountingIco(bytes(mutated_ico))
            trial_frames = _ico_frames(trial_ico)
            assert not trial_ico.slices and len(trial_frames) <= 512
            for frame in trial_frames:
                assert 1 <= frame.width <= 256 and 1 <= frame.height <= 256
                assert frame.byte_size > 0 and frame.image_offset >= 22
                assert frame.image_offset + frame.byte_size <= len(trial_ico)
            selected_png = _best_png_frame_from_ico(trial_ico, 144)
            assert len(trial_ico.slices) == (1 if selected_png is not None else 0)
            assert selected_png is None or selected_png.startswith(PNG_SIGNATURE)
        bounded_ico_file = test_dir / "bounded-read.ico"
        bounded_ico_file.write_bytes(ico_data)
        with patch.dict(globals(), MAX_ICO_FILE_BYTES=len(ico_data)):
            assert _read_ico_file_bytes(bounded_ico_file) == bytes(ico_data)
            assert len(_ico_frames(bytes(ico_data))) == 3
        with patch.dict(globals(), MAX_ICO_FILE_BYTES=len(ico_data) - 1):
            assert not _read_ico_file_bytes(bounded_ico_file)
            assert not _ico_frames(bytes(ico_data))
            assert not extract_embedded_png_icon(bounded_ico_file, None, 32)

        class ChangingIcoStream:
            def __init__(self, grow: bool) -> None:
                self.stream = bounded_ico_file.open("rb")
                self.grow = grow

            def __enter__(self) -> Any:
                return self

            def __exit__(self, *_args: Any) -> None:
                self.stream.close()

            def fileno(self) -> int:
                return self.stream.fileno()

            def read(self, size: int) -> bytes:
                with bounded_ico_file.open("r+b") as changing_file:
                    changing_file.truncate(len(ico_data) + (1 if self.grow else -1))
                return self.stream.read(size)

        for grows_during_read in (False, True):
            bounded_ico_file.write_bytes(ico_data)
            changing_path = type(
                "ChangingIcoPath", (),
                {"open": lambda _self, _mode: ChangingIcoStream(grows_during_read)},
            )()
            assert not _read_ico_file_bytes(changing_path), "size-changing ICO was accepted"
        extensionless_ico = test_dir / "ProductIcon"
        extensionless_ico.write_bytes(ico_data)
        extracted_frame = test_dir / "ProductIcon-frame.png"
        assert extract_embedded_png_icon(extensionless_ico, extracted_frame, 100)
        assert extracted_frame.read_bytes() == ico_payloads[1]
        assert standalone_ico_native_frame_size(extensionless_ico, 100) == (128, 128)
        standalone_ico = test_dir / "ProductIcon.ico"
        standalone_ico.write_bytes(ico_data)
        assert standalone_ico_native_frame_size(standalone_ico, 100) == (128, 128)
        native_frame_png = test_dir / "native-frame-32.png"
        write_rgba_png(
            native_frame_png,
            32,
            32,
            [bytes((32, 144, 224, 255)) * 32 for _ in range(32)],
        )
        native_frame_payload = native_frame_png.read_bytes()
        native_only_ico = test_dir / "native-only.ico"
        native_only_ico.write_bytes(
            struct.pack("<HHH", 0, 1, 1)
            + struct.pack(
                "<BBBBHHII",
                32,
                32,
                0,
                0,
                1,
                32,
                len(native_frame_payload),
                22,
            )
            + native_frame_payload
        )
        native_materialized = test_dir / "native-only-materialized.png"
        write_rgba_png(
            native_materialized,
            144,
            144,
            [bytes((240, 240, 240, 255)) * 144 for _ in range(144)],
        )
        assert materialize_icon_source_png(
            native_only_ico,
            native_materialized,
            small_shell_icon=False,
            target_size=144,
        )
        assert png_dimensions_fast(native_materialized) == (32, 32)
        nested_install = test_dir / "Example App"
        nested_bin = nested_install / "bin"
        nested_bin.mkdir(parents=True)
        nested_executable = nested_bin / "ExampleApp.exe"
        nested_executable.write_bytes(b"fixture")
        assert install_location_icon_path(str(nested_install), "Example App") == nested_executable
        decorated_install = test_dir / "Example Product 2"
        decorated_install.mkdir()
        decorated_executable = decorated_install / "Example Product 2.exe"
        decorated_executable.write_bytes(b"fixture")
        uninstaller_executable = decorated_install / "unins000.exe"
        uninstaller_executable.write_bytes(b"fixture")
        assert likely_uninstaller_icon_source(uninstaller_executable)
        assert not likely_uninstaller_icon_source(decorated_executable)
        assert (
            install_location_icon_path(
                str(decorated_install),
                "Example Product Trial version 2.1.2",
                "Example Product 2 APPID_is1",
            )
            == decorated_executable
        )
        assert (
            resolve_icon_source_fields(
                "winget",
                str(uninstaller_executable),
                r"ARP\Machine\X64\Example Product 2 APPID_is1",
                str(decorated_install),
                "Example Product Trial version 2.1.2",
                144,
            )
            == decorated_executable
        )
        plan_bytes = json.dumps({"schema": 1, "items": []}).encode("utf-8")
        plan_hash = hashlib.sha256(plan_bytes).hexdigest()
        assert parse_verified_elevation_plan_bytes(plan_bytes, plan_hash)["schema"] == 1
        duplicate_key_plan = b'{"schema": 1, "schema": 2, "items": []}'
        try:
            parse_verified_elevation_plan_bytes(
                duplicate_key_plan, hashlib.sha256(duplicate_key_plan).hexdigest()
            )
        except ValueError:
            pass
        else:
            raise AssertionError("elevation plan accepted duplicate JSON keys")
        nan_plan = b'{"schema": NaN, "items": []}'
        try:
            parse_verified_elevation_plan_bytes(nan_plan, hashlib.sha256(nan_plan).hexdigest())
        except ValueError:
            pass
        else:
            raise AssertionError("elevation plan accepted non-standard JSON constants")
        oversized_plan = b" " * (MAX_ELEVATION_PLAN_BYTES + 1)
        try:
            parse_verified_elevation_plan_bytes(
                oversized_plan, hashlib.sha256(oversized_plan).hexdigest()
            )
        except ValueError:
            pass
        else:
            raise AssertionError("an oversized elevation plan was accepted")
        try:
            parse_verified_elevation_plan_bytes(plan_bytes, "0" * 64)
        except ValueError:
            pass
        else:
            raise AssertionError("tampered elevation plan hash was accepted")
        transport_test_plan = {
            "schema": 1,
            "operation": ELEVATION_TRANSPORT_TEST_OPERATION,
            "items": [],
        }
        assert validate_elevation_transport_test_payload(transport_test_plan) is None
        try:
            validate_elevation_transport_test_payload(
                {**transport_test_plan, "items": [item.to_plan_dict()]}
            )
        except ValueError:
            pass
        else:
            raise AssertionError("elevation transport test accepted a package item")
        invalid_pipe_name = rf"\\.\pipe\{APP_NAME}-not-hex"
        try:
            validate_elevation_channel(invalid_pipe_name, os.getpid())
        except ValueError:
            pass
        else:
            raise AssertionError("an invalid elevation pipe name was accepted")
        if os.name == "nt":
            pipe_name = rf"\\.\pipe\{APP_NAME}-{uuid.uuid4().hex}"
            parent_process_id = os.getpid()
            assert validate_elevation_channel(pipe_name, parent_process_id) is None
            helper_arguments = elevation_helper_arguments(
                pipe_name, parent_process_id, plan_hash
            )
            assert "--elevated-authkey" not in helper_arguments
            assert "--elevated-plan" not in helper_arguments
            assert helper_arguments[-1] == plan_hash
            try:
                require_named_pipe_peer_process_id(
                    parent_process_id + 1, parent_process_id, "server"
                )
            except RuntimeError:
                pass
            else:
                raise AssertionError("an unexpected elevation pipe process was accepted")
            listener = Listener(pipe_name, family="AF_PIPE")
            receipt_queue: queue.Queue[Any] = queue.Queue(maxsize=3)
            receiver = threading.Thread(
                target=_serve_elevation_plan_and_receive_receipt,
                args=(listener, plan_bytes, receipt_queue, parent_process_id),
                daemon=True,
            )
            receiver.start()
            # An unrelated local process must be rejected before it receives
            # any plan bytes; the expected peer must still connect afterward.
            rejected_peer = subprocess.run(
                [
                    sys.executable, "-c",
                    "from multiprocessing.connection import Client\n"
                    "import sys\n"
                    "with Client(sys.argv[1], family='AF_PIPE') as client:\n"
                    "    if not client.poll(3):\n"
                    "        sys.exit(2)\n"
                    "    try:\n"
                    "        client.recv_bytes(1048576)\n"
                    "    except EOFError:\n"
                    "        sys.exit(0)\n"
                    "    sys.exit(3)\n",
                    pipe_name,
                ],
                capture_output=True, timeout=10, check=False,
                creationflags=subprocess.CREATE_NO_WINDOW,
            )
            assert rejected_peer.returncode == 0, rejected_peer.stderr
            with open_elevation_receipt_client(
                pipe_name, parent_process_id
            ) as receipt_client:
                assert named_pipe_server_process_id(receipt_client) == parent_process_id
                received_plan = receipt_client.recv_bytes(MAX_ELEVATION_PLAN_BYTES)
                assert parse_verified_elevation_plan_bytes(received_plan, plan_hash)["schema"] == 1
                send_elevation_receipt(
                    receipt_client,
                    {"schema": 2, "kind": "item_start", "sequence": 1},
                )
                send_elevation_receipt(
                    receipt_client,
                    {"schema": 2, "kind": "item_result", "sequence": 1},
                )
                send_elevation_receipt(receipt_client, {"schema": 1, "results": []})
            receiver.join(timeout=5)
            listener.close()
            assert not receiver.is_alive()
            streamed_messages = []
            while not receipt_queue.empty():
                receipt_bytes, receipt_error = receipt_queue.get_nowait()
                assert not receipt_error
                streamed_messages.append(json.loads(receipt_bytes))
            assert [message["schema"] for message in streamed_messages] == [2, 2, 1]
            assert [message.get("kind", "complete") for message in streamed_messages] == [
                "item_start",
                "item_result",
                "complete",
            ]
            saved_elevation_launcher = globals()["launch_elevated_and_wait"]
            interrupted_progress: list[str] = []

            def interrupted_elevation_launcher(
                parameters: Sequence[str],
                *,
                poll_callback: Callable[[], None] | None = None,
                process_started_callback: Callable[[int], None] | None = None,
            ) -> int:
                parameters = list(parameters)
                interrupted_pipe = parameters[parameters.index("--elevated-pipe") + 1]
                interrupted_parent = int(
                    parameters[parameters.index("--elevated-parent-pid") + 1]
                )
                interrupted_hash = parameters[
                    parameters.index("--elevated-plan-sha256") + 1
                ]
                assert process_started_callback is not None
                process_started_callback(os.getpid())
                with open_elevation_receipt_client(
                    interrupted_pipe, interrupted_parent
                ) as interrupted_client:
                    interrupted_plan = interrupted_client.recv_bytes(MAX_ELEVATION_PLAN_BYTES)
                    parsed_plan = parse_verified_elevation_plan_bytes(
                        interrupted_plan, interrupted_hash
                    )
                    assert parsed_plan["items"][0]["package_id"] == item.package_id
                    assert parsed_plan["items"][0]["current"] == item.current
                    send_elevation_receipt(
                        interrupted_client,
                        {
                            "schema": 2,
                            "kind": "item_start",
                            "key": item.key,
                            "sequence": 1,
                            "total": 1,
                        },
                    )
                if poll_callback is not None:
                    poll_callback()
                return 73

            try:
                globals()["launch_elevated_and_wait"] = interrupted_elevation_launcher
                execute_elevated_batch(
                    [item],
                    progress_callback=lambda kind, *_args: interrupted_progress.append(kind),
                )
            except RuntimeError as exc:
                assert "exited 73 without a completion receipt" in str(exc)
            else:
                raise AssertionError("an interrupted elevated helper was accepted as complete")
            finally:
                globals()["launch_elevated_and_wait"] = saved_elevation_launcher
            assert interrupted_progress == ["item_start"]
        dirty_alpha_row = bytes((10, 20, 30, 0, 40, 50, 60, 1, 70, 80, 90, 255))
        assert _rgba_has_dirty_transparent_rgb([dirty_alpha_row])
        assert _rgba_alpha_profile([dirty_alpha_row]) == (True, True)
        assert icon_gallery_needs_checkerboard([dirty_alpha_row])
        assert _sanitize_fully_transparent_rgb([dirty_alpha_row]) == [
            bytes((0, 0, 0, 0, 40, 50, 60, 1, 70, 80, 90, 255))
        ]
        clean_alpha_row = bytes((0, 0, 0, 0, 40, 50, 60, 255))
        assert not _rgba_has_dirty_transparent_rgb([clean_alpha_row])
        assert _rgba_alpha_profile([clean_alpha_row]) == (True, False)
        assert icon_gallery_needs_checkerboard([clean_alpha_row])
        assert icon_gallery_needs_checkerboard(
            [bytes((20, 30, 40, 255)) * 31 + bytes((20, 30, 40, 254))]
        )
        assert not icon_gallery_needs_checkerboard([bytes((20, 30, 40, 255)) * 32])
        pale_pixels = [(248, 248, 248, 255)] * 50 + [(220, 32, 48, 255)] * 14
        pale_rows = [
            bytes(channel for pixel in pale_pixels[y * 8 : (y + 1) * 8] for channel in pixel)
            for y in range(8)
        ]
        assert dominant_edge_outline_tone(pale_rows, 8, 8, (0, 0, 7, 7)) == "dark"
        dark_pixels = [(18, 18, 18, 255)] * 50 + [(28, 84, 220, 255)] * 14
        dark_rows = [
            bytes(channel for pixel in dark_pixels[y * 8 : (y + 1) * 8] for channel in pixel)
            for y in range(8)
        ]
        assert dominant_edge_outline_tone(dark_rows, 8, 8, (0, 0, 7, 7)) == "light"
        assert dominant_edge_outline_tone(pale_rows, 8, 8, (1, 1, 6, 6)) is None
        transparent_white_pixels = [(255, 255, 255, 0)] * 50 + [(220, 32, 48, 255)] * 14
        transparent_white_rows = [
            bytes(
                channel
                for pixel in transparent_white_pixels[y * 8 : (y + 1) * 8]
                for channel in pixel
            )
            for y in range(8)
        ]
        assert dominant_edge_outline_tone(
            transparent_white_rows, 8, 8, (0, 0, 7, 7)
        ) is None
        faint_white_pixels = [(255, 255, 255, 64)] * 50 + [(220, 32, 48, 255)] * 14
        faint_white_rows = [
            bytes(
                channel
                for pixel in faint_white_pixels[y * 8 : (y + 1) * 8]
                for channel in pixel
            )
            for y in range(8)
        ]
        assert dominant_edge_outline_tone(faint_white_rows, 8, 8, (0, 0, 7, 7)) is None
        remembered_miss = test_dir / "remembered-details-icon.png"
        with patch.dict(globals(), DISPLAY_ICON_CACHE_PREFIX="displayicon-v13-"):
            write_icon_render_miss(remembered_miss, 72, "former renderer fixture")
            assert icon_render_miss_is_current(remembered_miss, 72)
        assert not icon_render_miss_is_current(remembered_miss, 72)
        write_icon_render_miss(remembered_miss, 72, "fixture could not be rendered")
        assert icon_render_miss_is_current(remembered_miss, 72)
        assert not icon_render_miss_is_current(remembered_miss, 144)
        miss_path = icon_render_miss_path(remembered_miss, 72)
        stale_time = time.time() - ICON_RENDER_MISS_TTL_SECONDS - 1
        os.utime(miss_path, (stale_time, stale_time))
        assert not icon_render_miss_is_current(remembered_miss, 72)
        warm_miss_source = test_dir / "warm-list-miss-source.png"
        write_rgba_png(
            warm_miss_source,
            4,
            4,
            [bytes((32, 96, 160, 255)) * 4 for _ in range(4)],
        )
        warm_miss_item = UpdateItem(
            provider=WingetProvider.key,
            name="Warm miss fixture",
            package_id="WinDevPilot.SelfTest.WarmMiss",
            current="1",
            available="1",
            source="winget",
            icon_source=str(warm_miss_source),
        )
        warm_miss_size = 20
        warm_miss_raw = package_icon_cache_path_for_fields(
            warm_miss_item.provider,
            warm_miss_item.package_id,
            warm_miss_item.name,
            warm_miss_source,
            warm_miss_size,
            "light",
        )
        same_png_other_package = package_icon_cache_path_for_fields(
            "npm",
            "different-package-id",
            "Different package name",
            warm_miss_source,
            warm_miss_size,
            "dark",
        )
        same_png_details = details_icon_cache_path_for_fields(
            "cargo",
            "third-package-id",
            "Third package name",
            warm_miss_source,
            144,
        )
        assert warm_miss_raw == same_png_other_package == same_png_details
        assert warm_miss_raw.name.startswith(RAW_ICON_CACHE_PREFIX)

        synthetic_executable = test_dir / "source-versioned.exe"
        synthetic_executable.write_bytes(b"first-version")
        executable_list_20 = source_versioned_raw_icon_cache_path(
            synthetic_executable, 20, small_shell_icon=True
        )
        executable_list_96 = source_versioned_raw_icon_cache_path(
            synthetic_executable, 96, small_shell_icon=True
        )
        executable_details_144 = source_versioned_raw_icon_cache_path(
            synthetic_executable, 144, small_shell_icon=False
        )
        assert executable_list_20 == executable_list_96
        assert executable_list_20 != executable_details_144
        synthetic_executable.write_bytes(b"second-source-version")
        assert source_versioned_raw_icon_cache_path(
            synthetic_executable, 20, small_shell_icon=True
        ) != executable_list_20

        write_icon_render_miss(
            warm_miss_raw,
            warm_miss_size,
            "no usable icon could be extracted",
        )
        try:
            warm_sources, warm_ready, warm_unavailable, warm_error = (
                warm_icon_cache_index_isolated(
                    [warm_miss_item], warm_miss_size, "light", warm_miss_size
                )
            )
            assert not warm_error
            assert warm_sources[warm_miss_item.key] == warm_miss_source
            assert warm_miss_item.key not in warm_ready
            assert warm_unavailable == [warm_miss_item.key]
        finally:
            with contextlib.suppress(OSError):
                icon_render_miss_path(warm_miss_raw, warm_miss_size).unlink()
        icon_source = test_dir / "renderer-source.png"
        icon_rows = [bytes((24, 152, 214, 255)) * 12 for _ in range(12)]
        write_rgba_png(icon_source, 12, 12, icon_rows)
        icon_renderer = IconRenderCoordinator()

        warm_result: queue.Queue[bool] = queue.Queue(maxsize=1)
        warm_thread = threading.Thread(
            target=lambda: warm_result.put(icon_renderer.warm(0)), daemon=True
        )
        warm_thread.start()
        warm_thread.join(timeout=10.0)
        assert not warm_thread.is_alive()
        assert warm_result.get_nowait()
        warmed_child = icon_renderer._child
        assert warmed_child is not None and warmed_child.poll() is None

        def render_for_test(raw_path: Path, size: int, generation: int) -> tuple[bool, bool, str]:
            result_queue: queue.Queue[tuple[bool, bool, str]] = queue.Queue(maxsize=1)

            def render() -> None:
                result_queue.put(
                    icon_renderer.prepare(
                        icon_source,
                        raw_path,
                        size,
                        small_shell_icon=True,
                        fit_art_at_scale=None,
                        generation=generation,
                        priority=10,
                    )
                )

            render_thread = threading.Thread(target=render, daemon=True)
            render_thread.start()
            render_thread.join(timeout=ICON_RENDER_JOB_TIMEOUT_SECONDS + 10.0)
            assert not render_thread.is_alive()
            return result_queue.get_nowait()

        try:
            first_raw = test_dir / "renderer-first.png"
            assert render_for_test(first_raw, 40, 0)[0]
            first_display = display_icon_cache_path_for_file(first_raw, 40)
            assert first_display.exists()
            first_metadata_path = icon_render_metadata_path(first_display)
            assert first_metadata_path.exists()
            first_metadata = json.loads(first_metadata_path.read_text(encoding="utf-8"))
            assert first_metadata["schema"] == 1
            assert icon_render_metadata_is_current(first_metadata)
            assert first_metadata["resampling_policy"] == ICON_RESAMPLING_POLICY
            for stale_policy in (None, "former-renderer", "bilinear-future"):
                stale_metadata = dict(first_metadata)
                stale_metadata["resampling_policy"] = stale_policy
                assert not icon_render_metadata_is_current(stale_metadata)
            missing_policy = dict(first_metadata)
            missing_policy.pop("resampling_policy")
            assert not icon_render_metadata_is_current(missing_policy)
            assert not icon_render_metadata_is_current(dict(first_metadata, upscaled="false"))
            # One unchanged dimension can accompany genuine enlargement.
            narrow_metadata = dict(first_metadata, upscaled=True, upscale_scale_x=1.0,
                                   upscale_scale_y=2.0)
            assert icon_render_metadata_is_current(narrow_metadata)
            for bad_scale in (0, -1, float("inf"), float("nan")):
                assert not icon_render_metadata_is_current(
                    dict(narrow_metadata, upscale_scale_y=bad_scale)
                )
            assert first_metadata["source_file"] == str(icon_source)
            assert first_metadata["raw_png"] == str(first_raw)
            assert first_metadata["generated_png"] == str(first_display)
            assert first_metadata["source_canvas_width"] == 12
            assert first_metadata["source_canvas_height"] == 12
            assert first_metadata["source_visible_width"] == 12
            assert first_metadata["source_visible_height"] == 12
            assert first_metadata["source_has_explicit_alpha_channel"] is True
            assert first_metadata["source_uses_transparency"] is False
            assert first_metadata["source_uses_partial_alpha"] is False
            assert first_metadata["alpha_cleanup_applied"] is False
            assert isinstance(first_metadata["upscaled"], bool)
            assert isinstance(first_metadata["upscale_scale_x"], float)
            assert isinstance(first_metadata["upscale_scale_y"], float)
            if first_metadata["upscaled"]:
                assert first_metadata["upscale_scale_x"] > 1.0
                assert first_metadata["upscale_scale_y"] > 1.0
                legacy_metadata = dict(first_metadata)
                legacy_metadata.pop("upscale_scale_x")
                assert not icon_render_metadata_is_current(legacy_metadata)
            assert isinstance(first_metadata["adaptive_outline_applied"], bool)
            assert first_metadata["output_width"] == 40
            assert first_metadata["output_height"] == 40
            icon_details_text = WinDevPilotApp.item_details_text(
                details_probe,
                enriched_item,
                icon_evidence={"metadata_ready": True, **first_metadata},
            )
            assert "Icon artwork" in icon_details_text
            assert "Renderer: VPL64" not in icon_details_text
            assert "characters (excluding whitespace and comments)" not in icon_details_text
            vector_details_text = WinDevPilotApp.item_details_text(
                details_probe, enriched_item,
                icon_evidence={"generated_vector": "wrench"},
            )
            assert (
                f"Renderer: VPL64 {VPL64_ENGINE_VERSION} (language {VPL64_LANGUAGE_VERSION})"
                in vector_details_text
            )
            assert (
                f"Script: {len(''.join(V64_ICONS['wrench'].split()))} characters "
                "(excluding whitespace and comments)" in vector_details_text
            )
            assert "built-in vector illustration (wrench)" in vector_details_text
            assert f"Best source file: {icon_source}" in icon_details_text
            assert "Extracted canvas: 12 × 12 px" in icon_details_text
            assert "Explicit alpha channel: yes" in icon_details_text
            assert "Extracted raw PNG:" not in icon_details_text
            assert "Generated display PNG:" not in icon_details_text
            assert "Transparency present:" not in icon_details_text
            assert "Partial-alpha pixels present:" not in icon_details_text
            assert "Alpha cleanup applied:" not in icon_details_text
            assert "Adaptive contrast outline:" not in icon_details_text
            assert "GDI+ format normalization:" not in icon_details_text
            assert "right-click" not in icon_details_text
            assert ("Bilinear upscaling:" in icon_details_text) == first_metadata[
                "upscaled"
            ]
            if first_metadata["upscaled"]:
                assert "×" in icon_details_text
            first_child = icon_renderer._child
            assert first_child is not None and first_child.poll() is None
            assert first_child is warmed_child
            icon_renderer._discard_child(first_child)
            assert first_child.poll() is not None
            assert first_child.stdin is None or first_child.stdin.closed
            assert first_child.stdout is None or first_child.stdout.closed
            second_raw = test_dir / "renderer-recovered.png"
            assert render_for_test(second_raw, 48, 0)[0]
            replacement_child = icon_renderer._child
            assert replacement_child is not None and replacement_child.poll() is None
            assert replacement_child.pid != first_child.pid
            icon_renderer.set_generation(1, terminate=False)
            assert icon_renderer._child is replacement_child
            assert replacement_child.poll() is None
            stale_result = render_for_test(test_dir / "renderer-stale.png", 32, 0)
            assert stale_result == (False, False, "render request was superseded")
            assert render_for_test(test_dir / "renderer-current.png", 32, 1)[0]
            older_details_request = IconRenderRequest(
                1,
                icon_source,
                test_dir / "renderer-details-old.png",
                64,
                False,
                2.0,
                coalesce_key="details-test",
            )
            newer_details_request = dataclasses.replace(
                older_details_request,
                raw_path=test_dir / "renderer-details-new.png",
                completion=threading.Event(),
            )
            with icon_renderer._state_lock:
                icon_renderer._latest_coalesced["details-test"] = older_details_request
            assert icon_renderer._request_is_current(older_details_request)
            with icon_renderer._state_lock:
                icon_renderer._latest_coalesced["details-test"] = newer_details_request
            assert not icon_renderer._request_is_current(older_details_request)
            assert icon_renderer._request_is_current(newer_details_request)
            with icon_renderer._state_lock:
                icon_renderer._latest_coalesced.pop("details-test", None)
            assert icon_renderer.wait_idle(timeout=2.0)
            assert icon_renderer._inflight == 0
        finally:
            icon_renderer.shutdown(timeout=2.0)
        assert not icon_renderer._thread.is_alive()
        assert icon_renderer._inflight == 0
        previous_local_app_data = os.environ.get("LOCALAPPDATA")
        os.environ["LOCALAPPDATA"] = str(test_dir / "catalog-appdata")
        try:
            catalog_source = test_dir / "catalog-source.png"
            write_rgba_png(catalog_source, 12, 12, icon_rows)
            catalog_item = dataclasses.replace(
                item,
                name="Catalog fixture",
                package_id="Example.CatalogFixture",
                icon_source=str(catalog_source),
                installed_location="",
            )
            for size, is_list_icon in ((24, True), (144, False)):
                raw_path = (
                    package_icon_cache_path_for_fields(
                        catalog_item.provider,
                        catalog_item.package_id,
                        catalog_item.name,
                        catalog_source,
                        size,
                        "catalog",
                    )
                    if is_list_icon
                    else details_icon_cache_path_for_fields(
                        catalog_item.provider,
                        catalog_item.package_id,
                        catalog_item.name,
                        catalog_source,
                        size,
                    )
                )
                raw_path.parent.mkdir(parents=True, exist_ok=True)
                assert render_icon_cache_job(
                    catalog_source,
                    raw_path,
                    size,
                    small_shell_icon=is_list_icon,
                    fit_art_at_scale=None if is_list_icon else 2.0,
                )[0]
                if is_list_icon:
                    # Simulate a restart before a single Details icon exists.
                    early_entries = build_icon_catalog_entries(
                        (catalog_item,), {catalog_item.key: catalog_source},
                        24, 144, {}, full_inventory=False,
                    )
                    write_icon_catalog(early_entries)
                    early_loaded, early_blobs, early_error = load_icon_catalog_and_blobs()
                    assert not early_error and len(early_blobs) == 1
                    assert "list" in early_loaded[catalog_item.key]
                    assert "details" not in early_loaded[catalog_item.key]
            catalog_entries = build_icon_catalog_entries(
                (catalog_item,),
                {catalog_item.key: catalog_source},
                24,
                144,
                {},
                full_inventory=True,
            )
            assert set(catalog_entries) == {catalog_item.key}
            assert {"list", "details"} <= catalog_entries[catalog_item.key].keys()
            for missing_field in ("raw", "display"):
                missing_path = icon_cache_dir() / catalog_entries[catalog_item.key]["list"][missing_field]
                saved_stat = missing_path.stat()
                saved_artwork = missing_path.read_bytes()
                original_render_check = rendered_icon_cache_is_current

                def remove_after_validation(raw_path: Path, size: int) -> bool:
                    valid = original_render_check(raw_path, size)
                    if size == 24 and valid:
                        missing_path.unlink()
                    return valid

                try:
                    with patch(f"{__name__}.rendered_icon_cache_is_current", side_effect=remove_after_validation):
                        surviving_entries = build_icon_catalog_entries(
                            (catalog_item,), {catalog_item.key: catalog_source},
                            24, 144, catalog_entries, full_inventory=True,
                        )
                    surviving = surviving_entries[catalog_item.key]
                    assert "list" not in surviving and "list_unavailable" not in surviving
                    assert surviving["source_stat"] == catalog_entries[catalog_item.key]["source_stat"]
                    if missing_field == "display":
                        assert surviving["details"] == catalog_entries[catalog_item.key]["details"]
                    else:
                        # Direct PNG artwork shares its raw file across sizes.
                        assert "details" not in surviving and "details_unavailable" not in surviving
                finally:
                    missing_path.write_bytes(saved_artwork)
                    os.utime(missing_path, ns=(saved_stat.st_atime_ns, saved_stat.st_mtime_ns))
                # The next checkpoint can reuse restored artwork; no negative
                # extraction result was persisted for the transient absence.
                catalog_entries = build_icon_catalog_entries(
                    (catalog_item,), {catalog_item.key: catalog_source}, 24, 144, {},
                    full_inventory=True,
                )
                assert {"list", "details"} <= catalog_entries[catalog_item.key].keys()
            unresolved_item = dataclasses.replace(
                catalog_item, package_id="Example.NotLookedUp", name="Unresolved"
            )
            for full_inventory in (False, True):
                partial_entries = build_icon_catalog_entries(
                    (catalog_item, unresolved_item), {}, 24, 144, catalog_entries,
                    full_inventory=full_inventory,
                )
                assert partial_entries == catalog_entries
                assert unresolved_item.key not in partial_entries
                changed_identity = dataclasses.replace(catalog_item, name="Changed identity")
                mismatched_entries = build_icon_catalog_entries(
                    (changed_identity,), {}, 24, 144, catalog_entries,
                    full_inventory=full_inventory,
                )
                assert catalog_item.key not in mismatched_entries
            assert build_icon_catalog_entries(
                (), {}, 24, 144, catalog_entries, full_inventory=False,
            ) == catalog_entries
            assert not build_icon_catalog_entries(
                (), {}, 24, 144, catalog_entries, full_inventory=True,
            )
            confirmed_missing = build_icon_catalog_entries(
                (unresolved_item,), {unresolved_item.key: None}, 24, 144, {},
                full_inventory=True,
            )
            assert confirmed_missing[unresolved_item.key]["source"] == ""
            assert confirmed_missing[unresolved_item.key]["source_checked_at"] > 0
            assert build_icon_catalog_entries(
                (unresolved_item,), {}, 24, 144, confirmed_missing,
                full_inventory=True,
            ) == confirmed_missing
            write_icon_catalog(catalog_entries)
            loaded_entries, loaded_blobs, catalog_error = load_icon_catalog_and_blobs()
            assert not catalog_error
            assert set(loaded_entries) == {catalog_item.key}
            assert len(loaded_blobs) == 3
            list_display_paths = icon_catalog_list_display_paths(
                loaded_entries,
                set(loaded_blobs),
            )
            assert list_display_paths.keys() == {(catalog_item.key, 24)}
            assert list_display_paths[(catalog_item.key, 24)] in loaded_blobs
            writer_probe = object.__new__(WinDevPilotApp)
            writer_probe.__dict__.update(
                _closing=False, _cache_clear_inflight=False,
                _icon_catalog_write_pending=False, _icon_catalog_write_after_id=None,
                _icon_catalog_write_active=False, _icon_catalog_write_generation=0,
                _icon_catalog_write_lock=threading.Lock(),
                _icon_catalog_entries=catalog_entries,
                _icon_catalog_blobs={}, palette={"mode": "light"},
                _compact_icon_images={}, _compact_icon_tokens={},
                _icon_catalog_decode_queue=deque(), _icon_catalog_decode_after_id=None,
                _icon_catalog_loaded=False,
                _icon_catalog_valid_paths=set(), _icon_catalog_list_display_paths={},
                _last_scan_all_packages=True, _scan_results_current=True, _scan_active=False,
                items={catalog_item.key: catalog_item},
                _item_icon_source_cache={catalog_item.key: catalog_source},
                root=RebuildRootFixture(), events=queue.Queue(), logger=Mock(),
                _remember_details_icon_evidence=Mock(), _publish_resident_details_icon=Mock(),
                visuals=type("CatalogVisuals", (), {
                    "px": lambda _self, dip: 24 if dip == PACKAGE_ICON_SIZE_DIP else 144
                })(),
            )
            writer_started = threading.Event()
            release_writer = threading.Event()
            real_catalog_builder = build_icon_catalog_entries
            build_calls: list[bool] = []

            def held_catalog_builder(*args: Any, **kwargs: Any) -> dict[str, dict[str, Any]]:
                build_calls.append(kwargs["full_inventory"])
                if len(build_calls) == 1:
                    writer_started.set()
                    if not release_writer.wait(5):
                        raise ValueError("catalog fixture was not released")
                return real_catalog_builder(*args, **kwargs)

            with patch.dict(globals(), build_icon_catalog_entries=held_catalog_builder):
                writer_probe._schedule_icon_catalog_write()
                assert writer_probe._icon_catalog_write_pending
                assert not writer_probe.root.callbacks
                writer_probe._icon_catalog_loaded = True
                writer_probe._schedule_icon_catalog_write()
                writer_probe._schedule_icon_catalog_write()
                assert len(writer_probe.root.callbacks) == 1
                _callback_id, callback = writer_probe.root.callbacks.popitem()
                callback()
                try:
                    assert writer_started.wait(5)
                    # Later completions while one writer is busy become one follow-up.
                    for _ in range(4):
                        writer_probe._schedule_icon_catalog_write()
                    assert not writer_probe.root.callbacks
                    assert build_calls == [True]
                    writer_probe._scan_active = True
                finally:
                    release_writer.set()
                kind, payload = writer_probe.events.get(timeout=5)
                assert kind == "icon_catalog_written" and not payload[2]
                writer_probe._finish_icon_catalog_write(*payload)
                assert len(writer_probe.root.callbacks) == 1
                _callback_id, callback = writer_probe.root.callbacks.popitem()
                callback()
                kind, payload = writer_probe.events.get(timeout=5)
                assert kind == "icon_catalog_written" and not payload[2]
                writer_probe._finish_icon_catalog_write(*payload)
                assert build_calls == [True, False]
                assert not writer_probe._icon_catalog_write_active
                assert not writer_probe._icon_catalog_write_pending
                assert not writer_probe.root.callbacks
            # A queued write respects cache cleaning and close, without a flush.
            writer_probe._schedule_icon_catalog_write()
            writer_probe._cache_clear_inflight = True
            _callback_id, callback = writer_probe.root.callbacks.popitem()
            callback()
            assert not writer_probe._icon_catalog_write_active
            assert not writer_probe._icon_catalog_write_pending
            writer_probe._cache_clear_inflight = False
            writer_probe._closing = True
            writer_probe._schedule_icon_catalog_write()
            assert not writer_probe.root.callbacks
            stale_generation = writer_probe._icon_catalog_write_generation - 1
            writer_probe._closing = False
            writer_probe._finish_icon_catalog_write(stale_generation, {}, "", 0.0)
            assert writer_probe._icon_catalog_entries
            write_icon_catalog(catalog_entries)
            malformed_entries = {
                catalog_item.key: {
                    "list": {"size": "invalid", "display": "outside.png"}
                }
            }
            assert not icon_catalog_list_display_paths(malformed_entries, set(loaded_blobs))
            catalog_source.write_bytes(catalog_source.read_bytes() + b"changed")
            stale_entries, _stale_blobs, _stale_error = load_icon_catalog_and_blobs()
            assert catalog_item.key not in stale_entries
        finally:
            if previous_local_app_data is None:
                os.environ.pop("LOCALAPPDATA", None)
            else:
                os.environ["LOCALAPPDATA"] = previous_local_app_data
        background_probe = object.__new__(WinDevPilotApp)
        assert not WinDevPilotApp._background_event_work_active(background_probe)
        background_probe._date_sleuth_active = True
        assert WinDevPilotApp._background_event_work_active(background_probe)
        test_logger = SessionLogger(test_dir / "logs")
        test_logger.write("password=hunter2\nsecond line")
        test_logger.event(
            "diagnostic_test",
            credential="token=topsecret",
            process=command_result_entry(
                item,
                WingetProvider(),
                process_fixture,
                execution_context="self-test",
            ),
        )
        assert test_logger.flush()
        human_log = test_logger.path.read_text(encoding="utf-8")
        trace_record = json.loads(
            test_logger.trace_path.read_text(encoding="utf-8").splitlines()[0]
        )
        assert "hunter2" not in human_log and "topsecret" not in json.dumps(trace_record)
        assert len(human_log.splitlines()) == 2
        assert re.match(r"^\[\d{2}:\d{2}:\d{2}\.\d{2}\]", human_log)
        assert normalize_wall_clock_timestamp(trace_record["timestamp"])[1] == (
            "fractional-6"
        )
        assert trace_record["event"] == "diagnostic_test"
        assert trace_record["process"]["process_id"] == process_fixture.process_id
        assert trace_record["process"]["launcher_identity"]["account_fingerprint"]
        assert trace_record["process"]["outcome"] == "updated"
        assert trace_record["process"]["returncode_hex"] == "0x00000000"
        bundle_path = create_diagnostic_bundle(
            test_logger,
            {"providers": {"pip": False}, "attempt_holds": {}, "ignored": []},
            [item],
            destination_dir=test_dir / "bundles",
        )
        assert bundle_path.exists()
        with zipfile.ZipFile(bundle_path) as bundle:
            bundle_names = set(bundle.namelist())
            assert "README-diagnostic-bundle.md" in bundle_names
            assert "logs/current-session.log" in bundle_names
            assert "trace/current-session.jsonl" in bundle_names
            assert "visible-items.json" in bundle_names
            assert "settings-summary.json" in bundle_names
            assert not any(name.startswith("source/") for name in bundle_names)
            bundled_settings = json.loads(bundle.read("settings-summary.json"))
            assert bundled_settings["providers"]["pip"] is False
            assert bundled_settings["applicability_history_count"] == 0
            bundled_items = json.loads(bundle.read("visible-items.json"))
            assert bundled_items[0]["package_id"] == "Git.Git"
            bundled_log = bundle.read("logs/current-session.log").decode("utf-8")
            assert "hunter2" not in bundled_log
        assert bundle_path.stat().st_size <= DIAGNOSTIC_BUNDLE_MAX_BYTES
        saved_diagnostic_bundle_limit = globals()["DIAGNOSTIC_BUNDLE_MAX_BYTES"]
        oversized_bundle_dir = test_dir / "oversized-bundles"
        try:
            globals()["DIAGNOSTIC_BUNDLE_MAX_BYTES"] = 1
            create_diagnostic_bundle(
                test_logger,
                {"providers": {}, "attempt_holds": {}, "ignored": []},
                [item],
                destination_dir=oversized_bundle_dir,
            )
        except RuntimeError as exc:
            assert "diagnostic bundle exceeded the" in str(exc)
            assert "safety limit" in str(exc)
        else:
            raise AssertionError("an oversized diagnostic bundle was published")
        finally:
            globals()["DIAGNOSTIC_BUNDLE_MAX_BYTES"] = saved_diagnostic_bundle_limit
        assert oversized_bundle_dir.exists()
        assert not any(oversized_bundle_dir.iterdir())
        assert test_logger.close()

    class EscapeWindowProbe:
        def __init__(self) -> None:
            self.focused = 0
            self.destroyed = 0

        def focus_set(self) -> None:
            self.focused += 1

        def destroy(self) -> None:
            self.destroyed += 1

    class EscapeWidgetProbe:
        def __init__(self, widget_class: str, state: str = "normal") -> None:
            self.widget_class = widget_class
            self.state = state

        def winfo_class(self) -> str:
            return self.widget_class

        def cget(self, option: str) -> str:
            assert option == "state"
            return self.state

    escape_window = EscapeWindowProbe()
    editable_escape_event = type(
        "EditableEscapeEvent",
        (),
        {"widget": EscapeWidgetProbe("TEntry")},
    )()
    assert (
        WinDevPilotApp._close_toplevel_from_escape(
            escape_window, editable_escape_event
        )
        == "break"
    )
    assert escape_window.focused == 1 and escape_window.destroyed == 0
    assert (
        WinDevPilotApp._close_toplevel_from_escape(
            escape_window,
            type("WindowEscapeEvent", (), {"widget": escape_window})(),
        )
        == "break"
    )
    assert escape_window.destroyed == 1
    disabled_text_window = EscapeWindowProbe()
    WinDevPilotApp._close_toplevel_from_escape(
        disabled_text_window,
        type(
            "DisabledTextEscapeEvent",
            (),
            {"widget": EscapeWidgetProbe("Text", "disabled")},
        )(),
    )
    assert disabled_text_window.destroyed == 1

    class ConfiguredToplevelProbe:
        def __init__(self) -> None:
            self.bound: list[str] = []
            self.focused = 0
            self.lifted = 0
            self.configured: dict[str, Any] = {}

        def configure(self, **options: Any) -> None:
            self.configured.update(options)

        def bind(self, sequence: str, _callback: Any, *, add: str) -> None:
            assert add == "+"
            self.bound.append(sequence)

        def after_idle(self, callback: Callable[[], None]) -> None:
            callback()

        def winfo_exists(self) -> bool:
            return True

        def lift(self) -> None:
            self.lifted += 1

        def focus_set(self) -> None:
            self.focused += 1

    toplevel_app_probe = object.__new__(WinDevPilotApp)
    toplevel_app_probe._theme_toplevels = []
    toplevel_app_probe.palette = {"window": "#000000"}
    toplevel_app_probe._app_icon_image = None
    configured_toplevel = ConfiguredToplevelProbe()
    WinDevPilotApp._configure_toplevel(toplevel_app_probe, configured_toplevel)
    WinDevPilotApp._configure_toplevel(toplevel_app_probe, configured_toplevel)
    assert configured_toplevel.bound == ["<Escape>"]
    assert configured_toplevel.focused == configured_toplevel.lifted == 0

    class StartupSearchEntryProbe:
        def __init__(self) -> None:
            self.focused = 0
            self.cursor_positions: list[str] = []

        def focus_set(self) -> None:
            self.focused += 1

        def icursor(self, position: str) -> None:
            self.cursor_positions.append(position)

    class StartupSearchRootProbe:
        def __init__(self) -> None:
            self.focused_widget: Any = None

        def focus_get(self) -> Any:
            return self.focused_widget

    class StartupSearchTkProbe:
        TclError = RuntimeError

    startup_search_probe = object.__new__(WinDevPilotApp)
    startup_search_probe._closing = False
    startup_search_probe.tk = StartupSearchTkProbe()
    startup_search_probe.root = StartupSearchRootProbe()
    startup_search_probe.search_entry = StartupSearchEntryProbe()
    WinDevPilotApp._focus_startup_search(startup_search_probe)
    assert startup_search_probe.search_entry.focused == 1
    assert startup_search_probe.search_entry.cursor_positions == ["end"]
    startup_search_probe.root.focused_widget = object()
    WinDevPilotApp._focus_startup_search(startup_search_probe)
    assert startup_search_probe.search_entry.focused == 1

    class TreeFocusProbe:
        def __init__(self) -> None:
            self.focused = 0

        def identify_region(self, _x: int, _y: int) -> str:
            return "cell"

        def identify_column(self, _x: int) -> str:
            return "#1"

        def identify_row(self, _y: int) -> str:
            return "fixture-row"

        def focus_set(self) -> None:
            self.focused += 1

    tree_focus_app = object.__new__(WinDevPilotApp)
    tree_focus_app.tree = TreeFocusProbe()
    tree_focus_app.busy = True
    tree_focus_app._tree_display_column_name = lambda _column: "selected"
    WinDevPilotApp._tree_click(
        tree_focus_app,
        type("TreeFocusEvent", (), {"x": 1, "y": 1})(),
    )
    assert tree_focus_app.tree.focused == 1

    readme = SCRIPT_PATH.with_name("WinDevPilot_README.md")
    if readme.exists():
        assert APP_VERSION in readme.read_text(encoding="utf-8"), "README snapshot version is stale"
    project_metadata = SCRIPT_PATH.with_name("pyproject.toml")
    if project_metadata.exists():
        with project_metadata.open("rb") as stream:
            configured_version = str(tomllib.load(stream).get("project", {}).get("version", ""))
        assert configured_version == APP_VERSION, "pyproject.toml version is stale"
    assert dip_to_px(10, 96) == 10
    assert dip_to_px(10, 120) == 13
    assert dip_to_px(1, 144) == 2
    assert scale_geometry_spec("1280x820", 1.5) == "1920x1230"
    assert scale_geometry_spec("1280x820+10-20", 1.5, scale_position=True) == "1920x1230+15-30"
    assert scale_geometry_spec("not-geometry", 1.5) == "not-geometry"
    assert _extended_windows_path(r"\\.\PhysicalDrive0") == r"\\.\PhysicalDrive0"
    assert _extended_windows_path(r"\\?\C:\already-extended") == r"\\?\C:\already-extended"
    for identity_sample in (
        "", "Example Tool 2026", "Café — 工具™_最新版", "Straße®", "Ångström Builder",
        "a\u0301_b\0c", "１２３𝟜Ⅷ²", "\ud800 punctuation!\U0001f600",
        "".join(map(chr, range(512))),
    ):
        assert _portable_identity_text(identity_sample) == "".join(
            character for character in identity_sample.casefold() if character.isalnum()
        )
    for path_sample in (
        "", ".", "..", "../app/../", "~/app", "%TEMP%/app/../",
        "C:\\", "C:", "C:app", "\\app", "C:/Apps/../Tools/", "C:\\Apps\\Name. ",
        "//server/share", "//server/share/", "//server/share/app/../",
        "\\\\?\\C:\\", "\\\\?\\UNC\\server\\share\\", r"\\.\pipe\example",
    ):
        # Keep the old Path-anchor semantics, including drive/UNC root slashes.
        for path_value in (path_sample, Path(path_sample)):
            expanded = os.path.expandvars(os.path.expanduser(str(path_value)))
            normalized = os.path.normcase(os.path.abspath(expanded))
            anchor = Path(normalized).anchor
            expected_key = (
                normalized if anchor and normalized == anchor else normalized.rstrip("\\/")
            )
            assert _portable_path_key(path_value) == expected_key, repr(path_value)
    _portable_path_key.cache_clear()
    portable_key_probe = SCRIPT_PATH.parent / "portable-key-cache-probe"
    _portable_path_key(portable_key_probe)
    portable_cache_before = _portable_path_key.cache_info()
    _portable_path_key(portable_key_probe)
    portable_cache_after = _portable_path_key.cache_info()
    assert portable_cache_after.hits == portable_cache_before.hits + 1
    assert icon_gallery_prefetch_capacity(
        300,
        available_memory=16 * 1024**3,
    ) == 300
    assert icon_gallery_prefetch_capacity(
        300,
        available_memory=ICON_GALLERY_PREFETCH_MEMORY_RESERVE,
    ) == 0
    assert icon_gallery_blit_cache_limit(0) == 128 * 1024**2
    assert icon_gallery_blit_cache_limit(ICON_GALLERY_PREFETCH_MEMORY_RESERVE) == 0
    assert icon_gallery_blit_cache_limit(16 * 1024**3) == ICON_GALLERY_BLIT_CACHE_MAX_BYTES
    gallery_memory_probe = object.__new__(WinDevPilotApp)
    gallery_memory_probe.items = {"one": object(), "two": object()}
    gallery_memory_probe._icon_gallery_preparations = {"one": {}}
    gallery_memory_probe._icon_gallery_inflight = {}
    assert gallery_memory_probe._icon_gallery_preparations_at_capacity(
        available_memory=ICON_GALLERY_PREFETCH_MEMORY_RESERVE
    )
    assert not gallery_memory_probe._icon_gallery_preparations_at_capacity(
        available_memory=16 * 1024**3
    )
    gallery_memory_probe._icon_gallery_inflight = {"two": []}
    assert gallery_memory_probe._icon_gallery_preparations_at_capacity(
        available_memory=16 * 1024**3
    )
    gallery_memory_probe._icon_gallery_bundle_bytes = 33 * 1024**2
    gallery_memory_probe._icon_gallery_bundle_report_threshold = ICON_GALLERY_MEMORY_REPORT_START
    gallery_memory_probe.debug_mode = True
    gallery_memory_messages: list[str] = []
    gallery_memory_probe._append_log = lambda message: gallery_memory_messages.append(message)
    gallery_memory_probe.logger = type(
        "GalleryMemoryLogger", (), {"event": lambda _self, *_args, **_kwargs: None}
    )()
    gallery_memory_probe._report_icon_gallery_memory_growth()
    assert len(gallery_memory_messages) == 1
    assert gallery_memory_probe._icon_gallery_bundle_report_threshold == 64 * 1024**2
    gallery_memory_probe._report_icon_gallery_memory_growth()
    assert len(gallery_memory_messages) == 1
    gallery_memory_probe._icon_gallery_bundle_bytes = 65 * 1024**2
    gallery_memory_probe._report_icon_gallery_memory_growth()
    assert len(gallery_memory_messages) == 2
    assert gallery_memory_probe._icon_gallery_bundle_report_threshold == 128 * 1024**2
    gallery_memory_messages.clear()
    gallery_memory_probe._icon_gallery_blit_bytes = 0
    gallery_memory_probe._icon_gallery_blit_report_threshold = (
        ICON_GALLERY_BLIT_MEMORY_REPORT_START
    )
    gallery_memory_probe._adjust_icon_gallery_blit_memory(1 * 1024**2)
    assert len(gallery_memory_messages) == 1
    assert gallery_memory_probe._icon_gallery_blit_report_threshold == 2 * 1024**2
    gallery_memory_probe._adjust_icon_gallery_blit_memory(1 * 1024**2)
    assert len(gallery_memory_messages) == 2
    assert gallery_memory_probe._icon_gallery_blit_report_threshold == 4 * 1024**2
    gallery_memory_probe._adjust_icon_gallery_blit_memory(-(2 * 1024**2))
    assert gallery_memory_probe._icon_gallery_blit_bytes == 0
    gallery_memory_probe._icon_gallery_blit_cache = OrderedDict()
    gallery_memory_probe._icon_gallery_blit_limit = 8 * 1024**2
    fake_image = type(
        "FakeGalleryImage",
        (),
        {"width": lambda _self: 256, "height": lambda _self: 256},
    )()
    first_image = gallery_memory_probe._cached_icon_gallery_image(
        (b"digest", 1), lambda: fake_image
    )
    second_image = gallery_memory_probe._cached_icon_gallery_image(
        (b"digest", 1), lambda: (_ for _ in ()).throw(AssertionError("cache miss"))
    )
    assert first_image is second_image is fake_image
    assert gallery_memory_probe._icon_gallery_blit_bytes == 256 * 256 * 4
    gallery_memory_probe._icon_gallery_blit_limit = 256 * 256 * 4
    replacement_image = type(
        "ReplacementGalleryImage",
        (),
        {"width": lambda _self: 256, "height": lambda _self: 256},
    )()
    gallery_memory_probe._cached_icon_gallery_image(
        (b"replacement", 1), lambda: replacement_image
    )
    assert list(gallery_memory_probe._icon_gallery_blit_cache) == [(b"replacement", 1)]
    assert gallery_memory_probe._icon_gallery_blit_bytes == 256 * 256 * 4
    # Golden pixels from the pre-bounding kernels: padding, all canvas edges,
    # distant specks, dirty transparent RGB, and exact alpha thresholds.
    import random
    edge_rng = random.Random(20260902)
    edge_digest = hashlib.sha256()
    for edge_size in (3, 8, 19):
        for edge_kind in ("compact", "edge", "sparse", "opaque", "partial"):
            edge_rows: list[bytes] = []
            for y in range(edge_size):
                row = bytearray()
                for x in range(edge_size):
                    active = (
                        edge_size // 3 <= x < 2 * edge_size // 3
                        and edge_size // 3 <= y < 2 * edge_size // 3
                    ) if edge_kind == "compact" else (
                        x < edge_size // 2 if edge_kind == "edge"
                        else edge_rng.randrange(6) == 0 if edge_kind == "sparse"
                        else True
                    )
                    alpha = edge_rng.choice((0, 8, 9, 24, 25, 63, 64, 246, 247, 255)) \
                        if edge_kind == "partial" else (255 if active else 0)
                    row.extend((245, 245, 245, alpha))
                edge_rows.append(bytes(row))
            edge_digest.update(b"".join(
                _smooth_binary_alpha_edges(edge_rows, edge_size, edge_size)
            ))
            for tone in (None, "dark", "light"):
                result_tones: list[str] = []
                edge_digest.update(b"".join(add_adaptive_outline_to_rgba(
                    edge_rows, edge_size, edge_size,
                    forced_tone=tone, outline_result=result_tones,
                )))
                edge_digest.update(repr(result_tones).encode("ascii"))
    assert edge_digest.hexdigest() == (
        "266ad1b9e2a9c3b612c4cf57016881fd9cf43210f33b59618078c1a9550d6a75"
    )
    # Enlarged source pixels remain the input to ordinary rendering. The
    # migration changes display identity without re-extracting the raw PNG.
    with tempfile.TemporaryDirectory(prefix="wdp-source-pixels-") as art_tmp:
        art_root = Path(art_tmp)
        art_native = [
            b"".join(bytes((25, 142, 210, 255)) if (x + y) % 3
                     else bytes((244, 180, 30, 255)) for x in range(18))
            for y in range(18)
        ]
        for art_kind in ("repeated-pixels", "interpolated-pixels", "dim-colors"):
            art_rows = (
                [b"".join(row[x:x+4] * 3 for x in range(0, 72, 4))
                 for row in art_native for _ in range(3)]
                if art_kind == "repeated-pixels"
                else _scale_rgba_bilinear(art_native, 18, 18, 54, 54)
            )
            if art_kind == "dim-colors":
                art_rows = [bytes((40, 70, 100, 255)) * 54 for _ in range(54)]
            source = art_root / f"{art_kind}.png"
            raw_path = art_root / f"{art_kind}-raw.png"
            write_rgba_png(source, 54, 54, art_rows)
            with patch.dict(globals(), icon_cache_dir=lambda: art_root):
                assert materialize_icon_source_png(
                    source, raw_path, small_shell_icon=False, target_size=72
                )
                raw_identity = source_versioned_raw_icon_cache_path(
                    source, 72, small_shell_icon=False
                )
                display = display_icon_cache_path_for_file(raw_path, 72)
                with patch.dict(globals(), DISPLAY_ICON_CACHE_PREFIX="displayicon-v13-"):
                    legacy_display = display_icon_cache_path_for_file(raw_path, 72)
                    assert raw_identity == source_versioned_raw_icon_cache_path(
                        source, 72, small_shell_icon=False
                    )
                legacy_display.write_bytes(b"previous rendered artwork")
                assert legacy_display != display
                assert not rendered_icon_cache_is_current(raw_path, 72)
                assert render_icon_cache_job(
                    source, raw_path, 72, small_shell_icon=False,
                    fit_art_at_scale=2.0,
                )[0]
                assert read_png_rgba(raw_path) == (54, 54, art_rows)
                assert rendered_icon_cache_is_current(raw_path, 72)
                metadata = json.loads(
                    icon_render_metadata_path(display).read_text(encoding="utf-8")
                )
                assert metadata["source_canvas_width"] == 54
                assert not any(key.startswith(("bilinear_", "nearest_neighbor_", "pixel_grid_"))
                               for key in metadata)
                with patch.dict(globals(), render_icon_png_for_display=Mock(
                    side_effect=AssertionError("warm cache must not rerender")
                )):
                    assert render_icon_cache_job(
                        source, raw_path, 72, small_shell_icon=False,
                        fit_art_at_scale=2.0,
                    )[2] == "cached"
                assert legacy_display.read_bytes() == b"previous rendered artwork"
            request_metadata = json.dumps(
                {"artwork_width": 72, "artwork_height": 72, "backdrop": "checkerboard"}
            ).encode("utf-8")
            showcase_result = subprocess.run(
                cached_self_command("--icon-showcase-worker"),
                input=struct.pack("<I", len(request_metadata)) + request_metadata
                      + rgba_png_bytes(54, 54, art_rows),
                capture_output=True, timeout=30, check=False,
                cwd=str(SCRIPT_PATH.parent),
                creationflags=subprocess.CREATE_NO_WINDOW if os.name == "nt" else 0,
            )
            assert showcase_result.returncode == 0, showcase_result.stderr
            response_size = struct.unpack("<I", showcase_result.stdout[:4])[0]
            response_end = 4 + response_size
            showcase_metadata = json.loads(showcase_result.stdout[4:response_end])
            assert showcase_metadata["analysis"] == {"white_on_white_outline": False}
            assert "contrast_gain" not in showcase_metadata
            assert "contrast-" not in showcase_metadata["mode"]
            assert showcase_metadata["mode"] == "nearest-neighbor-upscale"
            expected_width, expected_height, padding = 80, 80, 4
            expected_rows = _pad_rgba(_scale_rgba_nearest(art_rows, 54, 54, 72, 72), 72, 72, 4)[2]
            assert read_png_rgba(showcase_result.stdout[response_end:]) == (
                expected_width, expected_height, expected_rows,
            )
            if art_kind == "dim-colors":
                center = expected_rows[padding + 36]
                assert center[(padding + 36) * 4:(padding + 37) * 4] == bytes((40, 70, 100, 255))
    assert [icon_showcase_background(state) for state in (0, 1, 4, 5, 8, 9, 12)] == [
        "white", "black", "checkerboard", "checkerboard", "white", "black", "checkerboard",
    ]
    # Exact replication preserves RGB even under zero alpha; no blended pixels.
    nearest_pixels = [bytes((10, 20, 30, alpha)) for alpha in (0, 64, 128, 255)]
    nearest_rows = [b"".join(nearest_pixels[:2]), b"".join(nearest_pixels[2:])]
    nearest_expected = [nearest_pixels[0] * 3 + nearest_pixels[1] * 3] * 3 + [
        nearest_pixels[2] * 3 + nearest_pixels[3] * 3
    ] * 3
    assert _scale_rgba_nearest(nearest_rows, 2, 2, 6, 6) == nearest_expected
    assert _scale_rgba_nearest(nearest_rows, 2, 2, 2, 2) == nearest_rows
    assert _scale_rgba_nearest(nearest_rows, 2, 2, 1, 1) == [nearest_pixels[3]]
    assert _scale_rgba_nearest(nearest_rows, 2, 2, 3, 1) == [
        nearest_pixels[2] + nearest_pixels[3] * 2
    ]
    assert _scale_rgba_nearest(nearest_rows, 2, 2, 0, 6) == []
    assert _scale_rgba_nearest([b"short"], 2, 1, 6, 3) == []
    for backdrop in ("white", "black", "checkerboard"):
        for color in ((255, 255, 255, 255), (0, 0, 0, 255), (40, 100, 200, 255), (255, 255, 255, 0)):
            original = [bytes(color) * 8] * 8
            finished, outlined = _showcase_finish_rows(original, 8, 8, backdrop)
            assert outlined == (backdrop == "white" and color == (255, 255, 255, 255))
            assert all(row[16:48] == original[y] for y, row in enumerate(finished[4:12]))
            if not outlined:
                assert finished == _pad_rgba(original, 8, 8, 4)[2]
    opaque_rows = [bytes((10, 20, 30, 255)) * 8 for _ in range(8)]
    assert _rgba_rows_opaque(opaque_rows)
    translucent_rows = list(opaque_rows)
    translucent_rows[3] = bytes((10, 20, 30, 128)) * 8
    assert not _rgba_rows_opaque(translucent_rows)
    assert _premultiply_rgba_rows([bytes((10, 20, 30, 255)) * 2]) == [
        bytes((10, 20, 30, 255)) * 2
    ]
    assert _premultiply_rgba_rows([bytes((10, 20, 30, 0)) * 2]) == [bytes(8)]
    assert _premultiply_rgba_rows([bytes((100, 50, 20, 128))]) == [
        bytes((50, 25, 10, 128))
    ]
    mixed_alpha_row = bytes(
        (
            255,
            127,
            1,
            1,
            255,
            127,
            1,
            64,
            255,
            127,
            1,
            254,
        )
    )
    assert _premultiply_rgba_rows([mixed_alpha_row]) == [
        bytes((1, 0, 0, 1, 64, 32, 0, 64, 254, 127, 1, 254))
    ]
    bbox_rows = [bytes(5 * 4) for _ in range(4)]
    bbox_row = bytearray(bbox_rows[2])
    bbox_row[1 * 4 + 3] = 25
    bbox_row[3 * 4 + 3] = 96
    bbox_rows[2] = bytes(bbox_row)
    assert _visible_rgba_bbox(bbox_rows, 5, 4, alpha_threshold=24) == (1, 2, 3, 2)
    assert _visible_rgba_bbox(bbox_rows, 5, 4, alpha_threshold=95) == (3, 2, 3, 2)
    assert _visible_rgba_bbox(bbox_rows, 5, 4, alpha_threshold=96) is None
    bilinear_rows = _scale_rgba_bilinear(opaque_rows, 8, 8, 12, 12)
    assert len(bilinear_rows) == 12 and bilinear_rows[6][0:4] == bytes((10, 20, 30, 255))
    assert len(_resize_rgba_for_icon(opaque_rows, 8, 8, 8, 8)) == 8
    assert len(_resize_rgba_for_icon(opaque_rows, 8, 8, 2, 2)) == 2
    assert len(_resize_rgba_for_icon(opaque_rows, 8, 8, 10, 10)) == 10
    assert len(_resize_rgba_for_icon(opaque_rows, 8, 8, 24, 24)) == 24
    bilinear_fixture = [
        bytes(channel for x in range(4) for channel in (
            (x * 61 + y * 17) % 256,
            (x * 23 + y * 73) % 256,
            (x * 89 + y * 31) % 256,
            (x * 47 + y * 53) % 256,
        ))
        for y in range(3)
    ]
    # Cover integral/non-integral downscales, mild/large enlargement, and
    # mixed-axis scaling; every non-identity route uses the same resampler.
    for target_width, target_height in ((2, 1), (3, 2), (5, 4), (11, 9), (2, 9), (1, 1)):
        resized = _resize_rgba_for_icon(
            bilinear_fixture, 4, 3, target_width, target_height
        )
        assert resized == _scale_rgba_bilinear(
            bilinear_fixture, 4, 3, target_width, target_height
        )
        assert len(resized) == target_height
        assert all(len(row) == target_width * 4 for row in resized)
        assert all(isinstance(row, bytes) for row in resized)
    identity_rows = _resize_rgba_for_icon(bilinear_fixture, 4, 3, 4, 3)
    assert identity_rows == bilinear_fixture and identity_rows is not bilinear_fixture
    for sizes in ((0, 3, 4, 3), (4, 0, 4, 3), (4, 3, 0, 3), (4, 3, 4, -1)):
        assert _resize_rgba_for_icon(bilinear_fixture, *sizes) == []
    uniform_opaque = [bytes((40, 70, 100, 255)) * 4 for _ in range(3)]
    assert _resize_rgba_for_icon(uniform_opaque, 4, 3, 11, 9) == [
        bytes((40, 70, 100, 255)) * 11
    ] * 9
    dirty_transparent = [bytes((12, 34, 56, 0)) * 4 for _ in range(3)]
    assert _resize_rgba_for_icon(dirty_transparent, 4, 3, 11, 9) == [bytes(11 * 4)] * 9
    # Hidden blue RGB must not darken or tint the interpolated red edge.
    alpha_edge = [bytes((255, 0, 0, 255, 0, 0, 255, 0))]
    assert _resize_rgba_for_icon(alpha_edge, 2, 1, 3, 1) == [
        bytes((255, 0, 0, 255, 255, 0, 0, 128, 0, 0, 0, 0))
    ]
    outline_fixture = [bytes(8 * 4) for _ in range(8)]
    for y in range(2, 6):
        outline_row = bytearray(outline_fixture[y])
        for x in range(2, 6):
            outline_row[x * 4 : x * 4 + 4] = b"\xff\xff\xff\xff"
        outline_fixture[y] = bytes(outline_row)
    outline_output = add_adaptive_outline_to_rgba(
        outline_fixture, 8, 8, forced_tone="dark"
    )
    assert hashlib.sha256(b"".join(outline_output)).hexdigest() == (
        "ede983ae25c690d3b76ade262066a1a077bf89ae61db32233260bca3afe19561"
    )
    merged_path = merge_windows_path_entries(
        r"C:\Existing;C:\Tools",
        r"c:\existing\;C:\New Tool",
    )
    assert merged_path.split(os.pathsep) == [r"C:\Existing", r"C:\Tools", r"C:\New Tool"]
    original_path = os.environ.get("PATH", "")
    try:
        os.environ["PATH"] = r"C:\Base;C:\Tools"
        recursive_path = merge_windows_path_entries(r"%PATH%;C:\New Tool")
        assert recursive_path.split(os.pathsep) == [
            r"C:\Base",
            r"C:\Tools",
            r"C:\New Tool",
        ]
    finally:
        os.environ["PATH"] = original_path
    path_report = refresh_process_path_from_windows_environment()
    assert isinstance(path_report, WindowsPathRefreshReport)
    assert all(isinstance(tool, str) for tool in path_report.affected_tools)
    idle_secondary_states = secondary_toolbar_action_states(
        busy=False,
        scan_active=False,
        all_packages=False,
        retry_available=True,
        report_available=True,
    )
    assert set(idle_secondary_states) == {
        "retry_failed",
        "select_recommended",
        "select_all",
        "select_none",
        "test_once",
        "save_system_report",
        "manage_ignores",
        "holds",
        "clean_graphics_cache",
        "providers",
    }
    assert all(state == "normal" for state in idle_secondary_states.values())
    inventory_secondary_states = secondary_toolbar_action_states(
        busy=False,
        scan_active=False,
        all_packages=True,
        retry_available=True,
        report_available=True,
    )
    assert inventory_secondary_states["select_recommended"] == "disabled"
    assert inventory_secondary_states["test_once"] == "disabled"
    busy_secondary_states = secondary_toolbar_action_states(
        busy=True,
        scan_active=False,
        all_packages=False,
        retry_available=True,
        report_available=True,
    )
    assert busy_secondary_states["retry_failed"] == "disabled"
    assert busy_secondary_states["save_system_report"] == "disabled"
    assert busy_secondary_states["providers"] == "normal"
    assert busy_secondary_states["clean_graphics_cache"] == "disabled"
    assert inventory_secondary_states["clean_graphics_cache"] == "normal"
    assert secondary_toolbar_action_states(
        busy=False, scan_active=False, all_packages=False,
        retry_available=False, report_available=False, cache_clear_inflight=True,
    )["clean_graphics_cache"] == "disabled"
    assert (
        secondary_toolbar_action_states(
            busy=False,
            scan_active=False,
            all_packages=True,
            retry_available=False,
            report_available=False,
        )["save_system_report"]
        == "disabled"
    )
    assert material_unavailable_provider_keys(
        {"winget": WingetProvider(), "pipx": PipxProvider()},
        {"winget": True, "pipx": True},
        {"winget": False, "pipx": False},
    ) == {"winget"}
    assert parse_args(["--debug"]).debug is True
    assert parse_args(["--developer"]).debug is True
    assert parse_args(["--validate-suggestions"]).validate_suggestions is True
    assert parse_args(["--elevation-smoke-test"]).elevation_smoke_test is True
    assert parse_args(["--index-icon-cache", "39", "light", "144"]).index_icon_cache == [
        "39",
        "light",
        "144",
    ]


def elevation_transport_smoke_test() -> int:
    """Exercise the real UAC transport with an exact plan that cannot mutate packages."""

    if os.name != "nt":
        print(
            json.dumps(
                {
                    "schema": 1,
                    "status": "unsupported",
                    "operation": ELEVATION_TRANSPORT_TEST_OPERATION,
                    "package_operations": 0,
                    "error": "elevation transport testing is only supported on Windows",
                },
                indent=2,
            )
        )
        return 2
    try:
        results = execute_elevated_batch((), operation=ELEVATION_TRANSPORT_TEST_OPERATION)
        if results:
            raise RuntimeError("transport test unexpectedly returned package results")
    except ElevationCancelled as exc:
        status = "cancelled"
        error = str(exc)
        returncode = 1
    except Exception as exc:
        status = "failed"
        error = f"{type(exc).__name__}: {exc}"
        returncode = 1
    else:
        status = "passed"
        error = ""
        returncode = 0
    print(
        json.dumps(
            {
                "schema": 1,
                "status": status,
                "operation": ELEVATION_TRANSPORT_TEST_OPERATION,
                "package_operations": 0,
                "parent_already_elevated": is_admin(),
                "error": error,
            },
            indent=2,
        )
    )
    return returncode


# ==================== Command-line entry points ====================

def parse_args(argv: Sequence[str] | None = None) -> argparse.Namespace:
    parser = argparse.ArgumentParser(description=__doc__)
    parser.add_argument(
        "--scan-json",
        action="store_true",
        help="scan enabled providers and print JSON without opening the GUI",
    )
    parser.add_argument(
        "--self-test", action="store_true", help="run parser and safety smoke tests"
    )
    parser.add_argument(
        "--validate-suggestions",
        action="store_true",
        help="verify the curated suggestion catalog and exact WinGet IDs, then exit",
    )
    parser.add_argument(
        "--display-diagnostics",
        action="store_true",
        help="report Windows/Tk DPI and square-corner configuration as JSON",
    )
    parser.add_argument(
        "--elevation-smoke-test",
        action="store_true",
        help="run a no-op UAC transport check without scanning or changing packages",
    )
    parser.add_argument(
        "--debug",
        "--developer",
        dest="debug",
        action="store_true",
        help="show internal decision-engine evidence in Package Details",
    )
    parser.add_argument("--elevated-pipe", default="", help=argparse.SUPPRESS)
    parser.add_argument("--elevated-parent-pid", type=int, default=0, help=argparse.SUPPRESS)
    parser.add_argument("--elevated-plan-sha256", default="", help=argparse.SUPPRESS)
    parser.add_argument("--render-worker", action="store_true", help=argparse.SUPPRESS)
    parser.add_argument("--icon-gallery-worker", action="store_true", help=argparse.SUPPRESS)
    parser.add_argument("--icon-showcase-worker", action="store_true", help=argparse.SUPPRESS)
    parser.add_argument(
        "--index-icon-cache",
        nargs=3,
        metavar=("SIZE", "PALETTE_MODE", "SOURCE_TARGET_SIZE"),
        help=argparse.SUPPRESS,
    )
    parser.add_argument("--version", action="version", version=APP_VERSION)
    return parser.parse_args(argv)


def main(argv: Sequence[str] | None = None) -> int:
    if sys.version_info < MIN_PYTHON:
        required = ".".join(map(str, MIN_PYTHON))
        message = (
            f"{APP_NAME} {APP_VERSION} requires Python {required}+.\n\n"
            f"Current Python: {platform.python_version()}\n"
            "Recreate the local environment with a newer Python, for example: uv venv"
        )
        if os.name == "nt":
            with contextlib.suppress(Exception):
                _user32().MessageBoxW(0, message, APP_NAME, 0x00000010)
        print(message, file=sys.stderr)
        return 2
    args = parse_args(argv)
    if args.render_worker:
        return icon_render_worker_main()
    if args.icon_gallery_worker:
        return icon_gallery_worker_main()
    if args.icon_showcase_worker:
        return icon_showcase_worker_main()
    if args.index_icon_cache:
        size_text, palette_mode, source_target_text = args.index_icon_cache
        try:
            icon_size = int(size_text)
            source_target_size = int(source_target_text)
        except ValueError:
            return 2
        if (
            not 8 <= icon_size <= 1024
            or not 8 <= source_target_size <= 1024
            or palette_mode not in {"light", "dark"}
        ):
            return 2
        return icon_cache_index_helper(icon_size, palette_mode, source_target_size)
    if (
        args.elevated_pipe or args.elevated_parent_pid or args.elevated_plan_sha256
    ):
        if not (
            args.elevated_pipe
            and args.elevated_parent_pid
            and args.elevated_plan_sha256
        ):
            print("all internal elevation arguments are required", file=sys.stderr)
            return 2
        return elevated_helper(
            args.elevated_pipe,
            args.elevated_parent_pid,
            args.elevated_plan_sha256,
        )
    if args.self_test:
        return self_test()
    if args.elevation_smoke_test:
        return elevation_transport_smoke_test()
    if args.validate_suggestions:
        return validate_package_suggestions_with_winget()
    if args.scan_json:
        migrate_legacy_app_data()
        return scan_json()
    if args.display_diagnostics:
        return display_diagnostics()
    if os.name != "nt":
        print(f"{APP_NAME} is currently Windows-only.", file=sys.stderr)
        return 2
    migrate_legacy_app_data()
    if not acquire_single_instance():
        _user32().MessageBoxW(
            0,
            f"{APP_NAME} is already running. Finish or close that window first;\n"
            "two concurrent update runs can block each other's installers.",
            APP_NAME,
            0x00000040,
        )
        return 0
    try:
        dpi_bootstrap = configure_windows_dpi_awareness()
        return WinDevPilotApp(dpi_bootstrap, debug_mode=args.debug).run()
    except Exception:
        try:
            crash_dir = app_data_dir()
            crash_dir.mkdir(parents=True, exist_ok=True)
            crash_path = crash_dir / "last-crash.log"
            crash_path.write_text(redact_sensitive_text(traceback.format_exc()), encoding="utf-8")
        except OSError:
            pass
        raise


if __name__ == "__main__":
    raise SystemExit(main())
