PASS: Chinese/path config round-trip
PASS: NetEase compatibility ignores idle windows and preserves song title separators
PASS: NetEase timeline does not interpret comment counts as playback time
PASS: NetEase playback and lyrics views parse their distinct timeline formats
PASS: minimized NetEase keeps advancing from the last live position while audio plays
PASS: silent audio session pauses the estimate without drifting
PASS: resumed audio continues the estimate
PASS: song change from the window title restarts the estimate with the queue duration
PASS: a live reading after restore replaces the estimate
PASS: NetEase play queue supplies track durations
PASS: music identifies all three requested clients
PASS: explicit music source never redirects to another client or browser
PASS: automatic music selection prefers playing clients
PASS: music timeline clamps stale or invalid positions
PASS: music settings and long-track timestamps normalize safely
PASS: magnet: snaps to work-area left edge within threshold and draws one guide
PASS: magnet: snaps right edge to work-area right edge
PASS: magnet: free placement beyond threshold is untouched
PASS: magnet: left edge abuts neighbour's right edge
PASS: magnet: aligns left edges with neighbour and guide spans both
PASS: magnet: aligns centres
PASS: magnet: aligns top edges vertically
PASS: magnet: equal spacing reproduces an existing 40px gap with gap guides
PASS: magnet: zero threshold disables snapping
PASS: new-widget argument is parsed case-insensitively
PASS: unknown or missing widget kinds are rejected
PASS: widget catalog lists 19 kinds (2.2.5: + 文件夹映射, 设备电量) with 便签 first
PASS: desktop menu command quotes the exe path
PASS: desktop menu registers cascading submenu with icon and one command per widget type
PASS: re-registering replaces the previous exe path
PASS: desktop menu unregisters cleanly
PASS: magnet and desktop-menu default on
PASS: notes round-trip text, colour and size
PASS: 1.9.x settings without notes load with defaults
PASS: only non-empty notes ask before deleting
PASS: Windows 11 top-level menu visibility defaults on
PASS: lock menu wording reflects state and action
PASS: dock click: app window that was foreground is minimized
PASS: dock click: an owned dialog in front counts as the app being foreground
PASS: dock click: app behind another window is brought forward (last active window)
PASS: dock click: minimized app is restored, not minimized again
PASS: dock click: unknown previous foreground activates
PASS: auto-hide: a window reaching into the Dock overlaps
PASS: auto-hide: touching edges is not overlap
PASS: auto-hide: hides only when enabled, overlapped and not in use by the pointer
PASS: manager: note preview uses the first non-empty line
PASS: manager: status text
PASS: quick: volume glyph follows level and mute
PASS: quick: volume percent is clamped and rounded
PASS: quick: WLAN status text
PASS: quick: denied / missing radios explain themselves
PASS: quick: Bluetooth status text
PASS: quick: WLAN glyph follows signal bars
PASS: quick: listed in 新建组件 catalog and 组件管理
PASS: quick: off by default
PASS: update: 2.1.0 is newer than 2.0.9
PASS: update: versions compare numerically (2.1.10 > 2.1.9)
PASS: update: v prefix, missing patch and 4th number
PASS: update: pre-release ordering follows semver
PASS: update: garbage version text is never 'newer'
PASS: update: equal and older versions are not offered
PASS: update: build metadata is ignored
PASS: update: the existing server versions.json parses (unsigned)
PASS: update: an unsigned manifest is not installable
PASS: update: malformed / oversized manifests are rejected
PASS: update: optional mirrors / changes / updateUrl fields parse
PASS: update: path-like package file names are refused
PASS: update: invalid sha256 text is refused
PASS: update: absurd package sizes are refused
PASS: update: SHA-256 known-answer test
PASS: update: ECDSA P-256 signature verifies
PASS: update: a changed payload fails verification
PASS: update: a signature from another key fails
PASS: update: empty / garbage signatures and keys never verify (and never throw)
PASS: update: an all-zero signature is rejected
PASS: update: a signed manifest verifies
PASS: update: changing version, size, hash, file name, updateUrl or mirrors invalidates the signature
PASS: update: notes / changes / dates are presentation only (not signed)
PASS: update: a manifest with the signature stripped is rejected
PASS: update: the embedded production public key is a valid ECDSA P-256 key
PASS: update: a manifest signed with a throw-away key is rejected by the production key
PASS: update: an unreachable source falls through to the next one
PASS: update: a tampered manifest is skipped (never trusted) and the next source is used
PASS: update: only a tampered manifest → no update, clear error
PASS: update: an unsigned manifest is refused
PASS: update: same version → up to date
PASS: update: all sources down and GitHub down → error, GitHub was tried as the fallback
PASS: update: a GitHub release without a signed manifest is notify-only, never installable
PASS: update: a GitHub release that carries a signed versions.json asset becomes installable
PASS: update: malformed GitHub responses are rejected
PASS: update: an interrupted download resumes from the bytes already stored (Range) and verifies
PASS: update: a server that ignores Range makes the client start over and still verify
PASS: update: an already downloaded, verified package is not downloaded again
PASS: update: a package whose SHA-256 differs from the signed manifest is rejected and deleted
PASS: update: more data than the manifest's size is rejected
PASS: update: a short package (wrong size) is rejected
PASS: update: a leftover partial file that belongs to another release is discarded, not resumed
PASS: update: cancelling the download stops it
PASS: update: the downloader refuses a manifest without a signature
PASS: update: source URLs are normalised to .../versions.json
PASS: update: only http(s) sources are accepted
PASS: update: default source is the Alibaba Cloud server
PASS: update: source order is user setting → config file → learned redirect → mirrors → built-in default (no duplicates)
PASS: update: with nothing configured only the default source is used
PASS: update: update-source.json is read (data folder first, then install folder) and can disable the GitHub fallback
PASS: update: a broken update-source.json is ignored
PASS: update: download paths resolve relative to the manifest, only http(s)
PASS: update: download tries the serving source first, then mirrors and configured sources
PASS: update: normal package paths are accepted (forward or back slashes)
PASS: update: zip-slip, rooted, drive, stream, device-name and empty paths are refused
PASS: update: payload root is found for a single top folder, a flat zip and backslash entries
PASS: update: packages without / with several / with a deeply nested ClearDesk.exe are refused
PASS: update: a normal package stages, nested folders included
PASS: update: a zip with backslash entries stages correctly
PASS: update: an entry changed after SHA256SUMS.txt was made is detected
PASS: update: a package without SHA256SUMS.txt is refused
PASS: update: a zip-slip entry is refused and nothing is written outside the staging folder
PASS: update: a file not listed in SHA256SUMS.txt is refused
PASS: update: a package without ClearDesk.exe is refused
PASS: update: a ClearDesk.exe that is not a Windows program is refused
PASS: update: a truncated zip is refused
PASS: update apply: changed files are replaced, new files (incl. new folders) are added
PASS: update apply: a file that existed only in the old release (and was untouched) is removed
PASS: update apply: files the user owns (notes, update-source.json, preview-data) are never touched
PASS: update apply: unchanged files are skipped and ClearDesk.exe is replaced last (before the checksum list)
PASS: update apply: no leftovers (old copies, journal, staging folder)
PASS: update apply: replaced and removed files are backed up under update\backup\<old version>
PASS: update apply: result file written, checksum list updated
PASS: update rollback: a failure while swapping the exe restores every file and removes added ones
PASS: update rollback: message says the old version was restored, journal cleaned
PASS: update rollback: a genuinely locked ClearDesk.exe makes the swap fail and roll back
PASS: update rollback: after a real lock failure the install folder is exactly as before
PASS: update apply: a staged file that no longer matches its checksum aborts before anything is touched
PASS: update recovery: an interrupted swap (crash / power loss) is undone at the next start
PASS: update recovery: nothing to do when there is no journal
PASS: update apply: a top taskbar left hidden by a crashed session is handed back before files are replaced
PASS: update apply: the taskbar is not touched when it was not hidden
PASS: update: write-permission probe detects a usable / unusable install folder
PASS: update: the Windows folder needs elevation for a standard user, so the app would show a message instead of updating
PASS: update: only --startup / --preview style switches are carried over to the restarted app
PASS: update: updater helper arguments round-trip (paths with spaces)
PASS: weather names: county-level extraction table (24 cases: 赛罕区, 黄浦区, 县级市, 无区城市, 繁体…)
PASS: weather names: Traditional → Simplified (區→区) and empty input
PASS: weather names: county-level test, street/town rejected, city stems match
PASS: reverse geocode: 呼和浩特市赛罕区 → shows 赛罕区 (Traditional 賽罕區 normalised)
PASS: reverse geocode: 上海市黄浦区 → shows 黄浦区
PASS: reverse geocode: a city without districts falls back to the city (东莞市), not the street
PASS: reverse geocode: county-level city shows its own name
PASS: reverse geocode: outside China keeps the city and never invents a district
PASS: reverse geocode fallback (OpenStreetMap): first county-level name in the address, not the neighbouring 玉泉区
PASS: reverse geocode fallback (OpenStreetMap): municipality 上海市黄浦区
PASS: reverse geocode: an empty answer is rejected instead of showing a blank place
PASS: ip service pconline parsed (names only)
PASS: ip service ipip.net parsed
PASS: ip service bilibili parsed with coordinates
PASS: ip service ipwho.is parsed and its Traditional city name (華盛頓哥倫比亞特區) is simplified
PASS: ip service ip-api.com parsed
PASS: ip service pconline: an address outside mainland China is flagged as not-China
PASS: ip service failure is an error, never a hard-coded city
PASS: ip vote: three domestic services agree (包头市 / 包头 are the same city), coordinates taken from the one that has them
PASS: ip vote: on a China time zone the foreign answers (proxy / VPN exit, e.g. 華盛頓) are discarded
PASS: ip vote: with only foreign answers they are used (nothing better exists)
PASS: ip vote: a non-China time zone does not discard anything; the majority still wins
PASS: ip vote: the majority city wins
PASS: ip vote: a tie goes to the higher-priority service
PASS: ip vote: no candidates → no result
PASS: weather source 腾讯天气: current conditions, 小雨 → rain, observation time
PASS: weather source 腾讯天气: forecast starts today (yesterday's entry dropped)
PASS: weather source 腾讯天气: wind level → km/h
PASS: weather source met.no: current conditions (m/s → km/h, local time)
PASS: weather source met.no: daily min/max grouped by local date, midday symbol
PASS: weather source wttr.in: current conditions and 3-day forecast
PASS: weather source Open-Meteo: current conditions and forecast
PASS: weather sources: an impossible temperature is rejected instead of displayed
PASS: weather sources: an error answer is rejected
PASS: weather code mapping: Tencent
PASS: weather code mapping: met.no
PASS: weather code mapping: wttr.in
PASS: weather code mapping: dust and haze labels, existing labels unchanged
PASS: weather source order in China: 腾讯天气 → Open-Meteo → met.no → wttr.in (腾讯天气>Open-Meteo>met.no>wttr.in)
PASS: weather source order elsewhere: Open-Meteo → met.no → wttr.in; the Chinese source is not used
PASS: a Chinese place without coordinates can still be read by name
PASS: a place with coordinates but no name uses the coordinate-based sources
PASS: weather refresh: about every 20 minutes after a success (±10%)
PASS: weather refresh: exponential backoff 1, 2, 4, 8, 15 minutes
PASS: weather refresh: backoff is jittered and capped
PASS: manual place: off by default
PASS: manual place: county name and coordinates come from the settings
PASS: manual place without coordinates is read by name
PASS: manual place: empty selection is ignored
PASS: dock restore: a minimized elevated app (ShowWindow refused) is restored through WM_SYSCOMMAND SC_RESTORE and brought forward
PASS: dock restore: no ShowWindow attempt is needed when SC_RESTORE worked
PASS: dock restore: when the app ignores SC_RESTORE the ShowWindow / OpenIcon fallback restores it
PASS: dock restore: when nothing works the result is Failed (the Dock then starts the app again)
PASS: dock restore: a window that vanished reports Gone
PASS: dock restore: a tray app's hidden window is shown again
PASS: dock restore: an elevated tray app cannot be shown from here → Failed so that the Dock relaunches it
PASS: dock minimize: elevated windows are minimized through SC_MINIMIZE
PASS: dock minimize: falls back to ShowWindow
PASS: tray app: a hidden captioned window of normal size is a main window
PASS: tray app: a visible window is not treated as hidden
PASS: tray app: IME / helper windows without a caption are ignored
PASS: tray app: tool windows are ignored
PASS: tray app: owned windows (dialogs) are ignored
PASS: tray app: untitled or tiny windows are ignored
PASS: launcher match: the pinned launcher is an ancestor of the client process
PASS: launcher match: explorer / shells as ancestors never group apps together
PASS: launcher match: a pinned cmd.exe does not claim programs started from a console
PASS: launcher match: unrelated processes do not match
PASS: todo: '18:30' is today at 18:30
PASS: todo: a clock time that already passed means tomorrow
PASS: todo: '明天 9:00'
PASS: todo: a day word without time means 09:00
PASS: todo: 'M/d H:mm'
PASS: todo: a past M/d means next year
PASS: todo: full date and time
PASS: todo: '30m' counts from now
PASS: todo: Chinese relative times
PASS: todo: nonsense is rejected
PASS: todo: due text
PASS: todo: an empty item is not added
PASS: todo: only items whose time has come are due
PASS: todo: an announced item does not remind twice
PASS: todo: later the next one becomes due
PASS: todo: a finished item never reminds
PASS: todo: un-checking re-arms the reminder
PASS: todo: reorder moves up/down and stops at the ends
PASS: todo: 'clear finished'
PASS: countdown: dates
PASS: countdown: past M/d rolls into next year; Chinese date
PASS: countdown: bad dates are rejected
PASS: countdown: days left and text
PASS: countdown: a yearly event counts to the next occurrence
PASS: countdown: 29 Feb falls on 28 Feb in other years
PASS: countdown: upcoming first, finished last
PASS: pomodoro: duration text
PASS: pomodoro: starts as a stopped 25:00
PASS: pomodoro: start counts down
PASS: pomodoro: pause freezes the time
PASS: pomodoro: Tick finishes exactly when the time is up
PASS: pomodoro: a finished focus round raises the event and prepares a short break
PASS: pomodoro: break → focus
PASS: pomodoro: every 4th round is followed by a long break
PASS: pomodoro: skipping does not count as a finished round
PASS: pomodoro: reset
PASS: netspeed: delta handles 32-bit wrap and counter reset
PASS: netspeed: the first sample only sets the baseline
PASS: netspeed: speed and today's total
PASS: netspeed: speeds use the real time between samples
PASS: netspeed: history is capped at 60 samples
PASS: netspeed: today's total survives a restart
PASS: netspeed: a total from yesterday is not restored
PASS: netspeed: the daily total restarts at midnight
PASS: netspeed: formatting
PASS: netspeed: Wi-Fi and Ethernet count
PASS: netspeed: VPN / virtual / down / loopback adapters do not count twice
PASS: sun: Hohhot 2026-10-26 sunrise 06:56 / sunset 17:37 (±3 min) → 06:56 / 17:37
PASS: sun: Shanghai 2026-10-26 sunrise 06:04 / sunset 17:11 (±3 min) → 06:04 / 17:11
PASS: sun: polar night and polar day are recognised
PASS: sun: day progress is about half at noon and empty at night
PASS: sun: day length text
PASS: air: AQI levels
PASS: air: Tencent AQI is parsed (national scale)
PASS: air: Open-Meteo AQI is parsed (US scale)
PASS: air: an answer without data is an error, not a zero
PASS: air: China → Tencent county, Tencent city, then Open-Meteo
PASS: air: outside China only Open-Meteo is used
PASS: air: both Tencent calls fail → falls back to Open-Meteo
PASS: air: when everything fails the result is null (the widget keeps its cache)
PASS: air: Tencent first, one call is enough
PASS: launcher: item kinds
PASS: launcher: URL normalisation
PASS: launcher: display names
PASS: launcher: no duplicates
PASS: launcher: at most 60 items
PASS: launcher: reorder and responsive columns
PASS: album: only images, sorted, no subfolders by default
PASS: album: subfolders on, duplicates removed
PASS: album: missing folders are ignored and the list is capped
PASS: album: sequential order and previous
PASS: album: a shuffled cycle shows every picture once and does not repeat across the cycle boundary
PASS: album: empty playlist and interval limits
PASS: album: DecodePixelWidth follows the box size and is capped (memory)
PASS: clipboard: the 'exclude from monitoring' format is skipped (password managers set it)
PASS: clipboard: CanIncludeInClipboardHistory = 0 is skipped
PASS: clipboard: CanIncludeInClipboardHistory = 1 is recorded
PASS: clipboard: password-manager owners are skipped, ordinary apps are not
PASS: clipboard: an unreadable flag does not crash
PASS: clipboard: newest first
PASS: clipboard: copying the same text again moves it to the top, no duplicate
PASS: clipboard: blank and oversized text is ignored
PASS: clipboard: pinned entries are listed first
PASS: clipboard: text cap keeps the newest and never drops pinned entries
PASS: clipboard: image cap drops the oldest image
PASS: clipboard: an image over the size limit is ignored
PASS: clipboard: total image memory is capped
PASS: clipboard: paused → nothing is recorded
PASS: clipboard: the saved form is encrypted (no plain text)
PASS: clipboard: encrypted text round-trips (DPAPI), images are never persisted
PASS: clipboard: a damaged file is ignored
PASS: clipboard: clear keeps pinned entries
PASS: clipboard: clear all
PASS: clipboard: single-line preview
PASS: schedule: '明天 14:00 项目评审'
PASS: schedule: 'M/d H:mm title'
PASS: schedule: no time → all day
PASS: schedule: no day → today
PASS: schedule: a title is required and times are validated
PASS: schedule: today = all-day first, then by time, multi-day events included
PASS: schedule: tomorrow and time text
PASS: schedule: .ics UTC times are converted to local time; escapes are decoded
PASS: schedule: .ics all-day events (exclusive end)
PASS: schedule: .ics folded lines and TZID times
PASS: schedule: re-importing replaces the imported events and keeps local ones
PASS: schedule: old events are pruned
PASS: store: a missing file loads as empty
PASS: store: atomic save leaves no temp file
PASS: store: todo data round-trips
PASS: store: countdown data round-trips
PASS: store: a damaged file is kept aside and the widget starts empty
PASS: store: clipboard history file holds no plain text
PASS: widgets: all 10 (2.2.5: + folder, battery) are registered in the settings list and in the 新建组件 menu
PASS: widgets: the old widgets are not tool widgets
PASS: pomodoro: 1–180 minutes are accepted
PASS: pomodoro: empty, zero, negative, decimal, text and over-range input is refused with a message
PASS: pomodoro: rounds before a long break are 2–12
PASS: pomodoro: stepper values are clamped
PASS: pomodoro: a hand-edited settings file is normalised (25/60/15/2)
PASS: pomodoro: presets are inside the allowed ranges
PASS: pomodoro: custom lengths are used
PASS: pomodoro: a long break comes after every 3rd focus round (W>S S>W W>S S>W W>L L>W)
PASS: placement: top-left at the cursor
PASS: placement: centred at the cursor
PASS: placement: kept inside the work area at the right / bottom edge
PASS: placement: second monitor is clamped to its own work area
PASS: placement: centred near the corner is clamped to the top-left
PASS: placement: a widget bigger than the screen is aligned to its top-left
PASS: placement: a point outside every screen uses the nearest work area
PASS: placement: monitor left of the primary one (negative coordinates)
PASS: placement: device pixels become DIPs by the DPI scale (zero scale is safe)
PASS: placement: snaps to the edge of another widget (800,100)
PASS: placement: no snapping when it is off (Alt held / setting off)
PASS: placement: snaps to the screen edge
PASS: placement: a right-click position is valid for 30 seconds only
PASS: placement: forgotten click gives the default placement
PASS: mixer model: expired and nameless sessions are dropped, the rest is grouped (5 rows)
PASS: mixer model: system sounds come first
PASS: mixer model: apps are sorted by name (系统声音|Alpha|plain|Virtual Mic|Zed Player)
PASS: mixer model: two sessions of one program are one row, controlled together
PASS: mixer model: name = session name, else file description, else program name, else pid
PASS: mixer model: slider position becomes a 0–1 level
PASS: mixer model: percent text and wheel steps are clamped
PASS: mixer model: unchanged rows keep the layout
PASS: mixer: set volume / mute reach the session; raising the volume of a muted app unmutes it
PASS: mixer: a row without a live session reports failure
PASS: system icons: this PC, recycle bin, control panel, user folder, network
PASS: system icons: recognised by their shell name (case-insensitive)
PASS: system icons: parsing name for the shell icon lookup
PASS: system icons: opened with explorer.exe shell:::{CLSID}
PASS: system icons: display names
PASS: system icons: with no setting only the recycle bin counts as on the desktop (Windows default)
PASS: system icons: icons switched on in the desktop icon settings are collected, hidden ones are not
PASS: system icons: only the recycle bin has a state icon
PASS: position: widgets on any monitor (also left of the primary, also in the taskbar strip) are reachable
PASS: position: widgets outside every monitor are not reachable
PASS: position: only moves the system makes while settling are kept out of the settings
PASS: position: a nudged widget goes back to its saved place; an unusable saved place is left alone
PASS: dock: the rebuild signature changes with the shown apps and their order only
PASS: dock: coming back from auto-hide is delayed; hiding and pointer peeks are immediate
PASS: metrics: the content scale is the smaller size ratio and stays within 0.6–4
PASS: metrics: outer padding grows with spare room, between 1× and 2×
PASS: metrics: padding is 20 at the default shape and never above 40
PASS: metrics: gaps between blocks grow with spare height, at most 3×
PASS: background: fit modes map to stretch modes; unknown values fall back to 'cover'
PASS: background: opacity and dimming are clamped
PASS: dock icons: exe icon missing → the window's own icon is used (window icon 0x2)
PASS: dock icons: exe, window, package, then the Start menu shortcut are tried in that order
PASS: dock icons: when every source fails the result is null (the Dock then shows a letter tile and retries)
PASS: dock icons: a fully transparent icon is treated as a failed lookup
PASS: dock icons: the shell's generic 'application' icon does not win over the window's icon
PASS: dock icons: the generic icon is still the last resort
PASS: dock icons: ApplicationFrameHost windows use the app's package icon, not the host's blank window icon
PASS: dock icons: a hosted app's icon request uses the app's own exe when it is known
PASS: dock icons: the letter tile is a real image; blank images are detected
PASS: 2.2.4 position: a saved place beyond the right edge is moved to the nearest visible place, not to the top-left default (1550,300)
PASS: 2.2.4 position: a place left of the second monitor goes to that monitor's edge
PASS: 2.2.4 position: an unusable (NaN) saved place is the only case that falls back to the default
PASS: 2.2.4 position: device pixels already right: nothing to do
PASS: 2.2.4 position: the same DPI but another place after the settle time: put back to the saved device pixels
PASS: 2.2.4 position: another DPI than at save time: the pixel record is not used
PASS: 2.2.4 position: a saved pixel place that is on no monitor now, or no pixel record: nothing to do
PASS: 2.2.4 settings: fresh profile (no settings.json) is reported as such
PASS: 2.2.4 settings: positions of the clock and performance widgets survive a kill without a normal exit (written when saved) 
PASS: 2.2.4 settings: the previous good file is kept as settings.json.bak
PASS: 2.2.4 settings: an empty settings.json is restored from settings.json.bak, positions intact
PASS: 2.2.4 settings: a truncated settings.json is restored from settings.json.bak
PASS: 2.2.4 settings: corrupt with no backup is reported as corrupt (defaults), not as locked
PASS: 2.2.4 settings: a settings.json that is locked while reading is reported as blocked (not as missing)
PASS: 2.2.4 settings: a read that is blocked for a moment is retried and the real positions are loaded
PASS: 2.2.4 settings: a write that hits sharing violations is retried until it succeeds
PASS: 2.2.4 settings: access denied is retried, then reported without touching the existing file
PASS: 2.2.4 settings: a real exclusive lock (antivirus) for a moment does not lose the save
PASS: 2.2.4 settings: legacy file with mixed-case widget keys keeps the clock and performance positions
PASS: 2.2.4 settings: a 2.0.x file without widget records loads (defaults are placed once and then saved)
PASS: 2.2.4 settings: a NaN position only resets that widget, the other is kept
PASS: 2.2.4 settings: an impossible number never produces an unreadable settings.json
PASS: 2.2.5 version string (2.2.9)
PASS: 2.2.5 folder widget: registered as a widget kind with several instances
PASS: 2.2.5 TB-04: the notice title tells 'in use' from 'content differs'
PASS: 2.2.5 TB-04: silent retry backoff is 1,2,4,8,15,30 s
PASS: 2.2.5 360: ClearDesk.exe no longer carries the TranslucentTB files (only their manifest)
PASS: 2.2.5 360: the exe has a complete version resource (2.2.9.0, visual-life)
PASS: 2.2.5 TB-04: running TranslucentTB copies are classified (Store version / ClearDesk's own folder / elsewhere)
PASS: 2.2.5 TB-04: the description names the Store version and ClearDesk's own copy
PASS: 2.2.5 folder widget: folders first, natural order, hidden files left out (A dir,b dir,file2.txt,file10.txt)
PASS: 2.2.5 folder widget: 'show hidden files' shows them
PASS: 2.2.5 folder widget: a missing folder gives a message, no crash
PASS: 2.2.5 folder widget: wider widget -> more columns
PASS: 2.2.6 version string
PASS: 2.2.6 folder list: row icon is 16-20 px (18)
PASS: 2.2.9 version string
PASS: 2.2.9 launchpad: pinned first in their saved order, then desktop items, removed ones hidden (x,b,a)
PASS: 2.2.9 --pin-launchpad takes every path after it
PASS: 2.2.9 classic Explorer verb command line
PASS: 2.2.9 compact bar scale grows with the width and never drops below 0.9
PASS: 2.2.9 runas offered for .exe and a shortcut to an .exe
PASS: 2.2.9 runas hidden for store / UWP apps, folders, documents, links and system icons
PASS: 2.2.9 runas: ShellExecute with the runas verb (fake starter, no UAC prompt)
PASS: 2.2.9 runas: cancelling UAC (1223) is silent and returns false
PASS: 2.2.9 固定到启动台 registered for files
PASS: 2.2.9 固定到启动台 registered for folders
PASS: 2.2.9 固定到启动台 removed again
PASS: 2.2.8 version string
PASS: 2.2.8 header scale depends on the window size only and is monotonic in height
PASS: 2.2.8 hysteresis: a 1 px step that moves the list < 3 px keeps the size
PASS: 2.2.8 hysteresis: a real change is applied
PASS: 2.2.8 hysteresis: >= 3 px of height applies the 1 px step
PASS: 2.2.7 version string
PASS: 2.2.7 list size: tall narrow widget with 7 items -> big rows that fill most of the height (icon 42 / font 20.5 / row 62, 434 of 470)
PASS: 2.2.7 list size: many items -> base size and scrolling (icon 16 / font 12 / row 26)
PASS: 2.2.7 list size: a narrow widget is limited by its width so names keep room (icon 23 / font 14.5 / row 34)
PASS: 2.2.7 list size: upper limits 48 px icon / 22 px text (icon 48 / font 22 / row 70)
PASS: 2.2.7 list size: lower limits 16 px icon / 12 px text (icon 16 / font 12 / row 26)
PASS: 2.2.7 list size: taller -> never smaller
PASS: 2.2.7 list size: a wide but low widget is limited by its height, not its width (icon 25 / font 14.5 / row 36)
PASS: 2.2.7 icon view: tall widget with few items -> bigger tiles; many items -> base size (60, 44, 44)
PASS: lunar conversion 九月初十 · 丙午年
PASS: weather code mapping
PASS: known Lunar New Year reference (2026-02-17)
PASS: mouse hook registered and released
PASS: window event hook registered and released
PASS: Explorer desktop discovery (read-only)
PASS: 1 taskbars discovered (read-only)
PASS: 19 desktop references enumerated (read-only)
