# Changelog
All notable user-visible changes are recorded here. The format follows
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and versions follow Semantic Versioning
where practical.
## [Unreleased]
### Fixed
- A genuine-input notification from an earlier session no longer pauses the session
that replaced it. Input from the current session still starts the cooldown.
- A repeated settings key now warns and keeps the later value. A value that is not an
integer warns as non-numeric instead of out of range. Either warning keeps automatic
start stopped until the settings are reviewed and saved.
- A settings path that exists but cannot be opened, including a directory, is now a
recovery warning instead of a missing file. A path that is not there is still a first run.
### Changed
- Settings scrolling responds proportionally to small wheel movements; wheel notches
settle with a short, interruptible transition that respects reduced motion.
A slim themed scrollbar retains native dragging and accessibility behavior.
Page Up/Down and Home/End navigate settings from buttons, preserving editing keys.
Buffered control painting and native press/release redraws improve interaction feedback.
- Session duration leads the main view. Expandable settings now show current motion,
safeguard and appearance summaries in a quieter second line, including native
accessible names; unfinished edits remain intact.
- Dark appearance with matching native dropdowns and an optional native Mica
backdrop. Window & notifications contains saved light/dark and soft/solid switches;
appearance changes preserve unfinished settings edits and remain available while running.
- Native field-paint regression checks accept the specified hover colour, avoiding
cursor-dependent failures.
- Refined the compact window with a soft neutral surface, clearer typography,
rounded controls, quiet disclosure rows and a blue primary session action.
Native keyboard/editing behaviour and Windows high-contrast rendering remain.
### Added
- Compact native settings window with duration presets, exact custom seconds and
expandable Motion & timing, Safety pauses and Window & notifications sections.
Status and Start/Stop/Save remain fixed; the title shows the running version.
- Session-only tray timers (15/30/60/120 minutes), manual Pause/Resume, bounded snooze,
deadline extension and live remaining-time status/tooltip. Strict CLI equivalents use the
existing duration syntax; elapsed limits and automatic safeguards remain authoritative.
### Fixed
- Invalid Start or Save keeps unfinished entries, opens their settings section and
focuses the field to correct. Collapsed motion summaries flag invalid size and
interval values even with motion off; rejected edits never partially apply.
- Keyboard entry starts at Session duration, and hiding a preset-matching custom
duration returns focus to its selector. Pointer movement within a control now
repaints only the hover transition instead of every move.
- Full-window glass could hide native controls until a capture overlay changed
composition. The optional material now stays in the title bar, while the whole
control area remains opaque. Capture tests no longer bypass the material path.
- Documentation capture explicitly quotes spaced configuration paths, reuses its native helper
on repeated invocation and disables the emergency hotkey in capture-only settings.
- Starting a guarded session retries transient Windows session-notification registration failures
instead of requiring an application restart after automatic startup. Registration and the current
lock/disconnect state must both succeed before Start is allowed.
- Failed power release is visible in application status and leaves Stop enabled for retry;
a new session is blocked until cleanup succeeds. Old tray-menu session actions are discarded
after expiry or replacement, including same-tick replacement.
- Tray failure no longer replaces paused or stopped reasons with generic status. Recovery retracts
only the transient icon warning, and native status text, the tooltip and `--status` retain the
same unsaved-settings prefix and underlying reason.
- Input-hook cleanup retains failed handles, disables notifications immediately, and bounds
refresh/destructor recovery to four pending handles without allowing duplicate observers.
- Configuration filenames beginning with a single dash are accepted without swallowing recognized
options; 109 parser boundary cases protect missing-value handling and following commands.
- Per-user install and uninstall bound the new exit-command child wait, reject identified foreign
or unknown sessions, dispose handles and preserve preview no-launch behavior.
- Installer previews explicitly report preview-only summaries and distinguish genuinely unowned
residue from managed files retained by WhatIf. Hash and timestamp checks protect no-op behavior.
- Failed power-request cleanup retains the last applied state for retry; Apply(None) reports the
cleanup result instead of claiming unconditional success.
- Interval sampling rejects nonpositive or reversed bounds while preserving valid deterministic,
fixed and random behavior. All safety-pause status reasons have executable coverage.
- InputMonitor rejects a missing notification window or zero message before installing observers,
and releases the attempted ownership claim on rejection.
- Chocolatey upgrade and uninstall share session-aware shutdown, reject uncertain process
ownership or failed discovery, and bound the spawned `--exit` command instead of waiting
indefinitely. Process handles are released on success and failure; running application instances
are not force-terminated.
- `--stop-after` now accepts durations up to 30 days (720 hours), matching the settings validator.
The CLI previously rejected durations above seven days even though the settings allowed them.
- The window's minimum height now includes its title bar and borders. The minimum was set from the
content height alone, so dragging the window to its smallest size let the frame eat into the
content and clipped the fixed Start/Stop/Save footer.
- Starting a session with the lock or disconnect safeguard enabled no longer fails permanently on a
copy of IdleHarbor that was launched while the workstation was locked. The lock state is read
from the input desktop, which Windows withholds behind the lock screen, and that one startup
reading was kept for the life of the process: a relaunch at sign-in left "IdleHarbor could not
establish the current lock/disconnect state" on every Start until the process was exited from the
tray and started again. The state is now re-established when a session is started and on every
lock, unlock, connect, and disconnect notification, and the stopped status card retracts the
claim once the state is readable.
- An option missing its value no longer swallows the next option: `--config --start` now reports
that `--config` requires a value instead of using `--start` as the configuration path. The parser
retains the following command in its result, including Stop for `--interval --stop`; the
application still rejects the errored invocation without executing that command.
### Distribution
- Capture manifests use deterministic two-space LF JSON across both PowerShell editions;
read-only checks verify the hashes and dimensions of the five committed PNGs.
- The packaging fixture suite runs in an edition-matched child PowerShell process so its test
doubles cannot overwrite the caller's scheduler command, module binding or fixture variable.
- Publication requires the complete normalized GPLv3 text, not only recognizable license markers;
valid LF, CRLF and UTF-8 BOM representations are tested without changing the license itself.
- Chocolatey metadata may lag only to the immediate previous dated release, preserving the
legitimate release/repoint window while rejecting stale or ambiguous histories.
- Read-only automated checks download and hash the pinned Chocolatey archive and all tracked
WinGet archives. Offline WinGet contracts guard identity, version, architecture and nested paths.
- Release packaging requires every documented payload, including the distribution guide, before
touching an existing archive. The same source/destination table drives validation and copying.
- CI executes the input-monitor contract, release-version, archive and Chocolatey shutdown
regressions in both Windows PowerShell 5.1 and PowerShell 7 without an installed Pester module.
- The website's six release references are checked together, independently of the in-development
CMake version. Hosting plans identify their canonical-routing and release-verification source
files without activating a deployment or changing the canonical site.
- The project website (not the application) now runs the Pulseboard beta SDK 3.3.0 with a Beta
consent bar: aggregate usage counts, optional diagnostics and journeys, and which release or
source link was chosen. Global Privacy Control and Do Not Track turn it off. The
application itself is unchanged: it has no telemetry and no network access, and the site and
README now say so explicitly.
- The project has a site at , published from `docs/`. It
describes the motion modes, the safeguards, and the download and verification steps, and is linked
from the README and the user guide.
- The project site is now mirrored on Cloudflare Workers at
, which adds a `/download` route that always resolves
to the current release. remains the canonical site and
is unchanged; the mirror exists so the site can serve a root `robots.txt` and response headers,
which a GitHub Pages subdirectory cannot.
## [0.2.0] - 2026-08-24
### Added
- Each settings field now carries a short explanation printed under it, so the window can be read
straight through without hovering anything.
- Every settings control also explains itself in more detail on hover, including the labels, the
Start, Stop, and Save actions, and the status card. Hovering a label gives the same description as the field beside
it. During a running session the settings are disabled and Windows does not deliver hover to a
disabled control, so only the labels, the status card, and Stop still describe themselves.
### Changed
- The maximum session duration moved from "Window & notifications" to "Safeguards". It is a session
setting that a profile replaces, unlike everything else under the former heading.
- Renamed four labels for what they do rather than how: "Power request" is now "Keep awake",
"Motion multiplier" is now "Motion size", "Pause after genuine input" is now "Pause after real
input", and the low-battery threshold now names its unit. The out-of-range message for the motion
size was still calling it a multiplier and now matches the label.
### Fixed
- Selecting a profile, motion mode, or power request now updates the field immediately instead of
appearing to keep its previous value until focus moved elsewhere.
- Clicking a combo box no longer scrolls the settings body out from under the pointer, so a mode can
be picked on the first attempt. The body holds still while any drop-down list is open.
- Scrolling the settings body moves its controls as one surface instead of repositioning them one at
a time.
- The status card now reports unsaved changes before the Save action is relabelled or enabled, instead
of briefly showing an available Save action beside a saved-looking status.
- Dismissing the profile list with Escape, or re-selecting the profile already in effect, no longer
reloads that profile's defaults over settings you had edited.
### Distribution
- Published under `GPL-3.0-only` as unsigned x64 and ARM64 portable archives accompanied by
SHA-256 checksums, per-architecture SPDX SBOMs, and GitHub artifact attestations, on the same
terms as `0.1.0`.
## [0.1.0] - 2026-08-20
### Added
- GNU General Public License version 3 only (`GPL-3.0-only`), with the complete licence and a
transparent implementation-provenance notice included in source and portable distributions.
- Ownership-safe per-user Start Menu launcher creation (enabled by default) with independent
`-StartMenu Create|None` control, exact-link preflight, marker ownership, and transactional byte
rollback; automatic startup remains independently disabled by default.
- Native visible Win32 window and notification-area controls with explicit Start, Stop, Show, and Exit paths.
- Motion modes: Off, Normal, Zen, Circle, and Linear.
- Named Balanced, Long Task, Presentation, Compatibility, Visible, Battery Saver, and Custom profiles.
- Validated local INI settings with portable and explicit-config paths.
- Genuine-input, lock/session, battery, fullscreen, active-hours, maximum-duration, and emergency-stop controls.
- Strict command-line parsing with visible help, version, status, session commands, and bounded options.
- Per-user installer, ownership marker, WhatIf preview, uninstall, and opt-in Task Scheduler/Startup-folder/HKCU Run choices.
- CI build matrix, pinned actions, CodeQL workflow, portable release packaging, checksums, SPDX SBOMs, and GitHub attestations.
- Per-monitor-DPI-aware resize and scrolling that keeps every setting and action keyboard reachable.
- Reproducible 192-DPI documentation captures for stopped, running, intelligently paused, scrolled,
and notification-area states, with exact executable and image hashes in a machine-readable manifest.
- Fixed the live status and immediate Start/Stop actions outside the scrolling settings body; narrow
work areas now reflow settings and wrap or stack actions, and focus reveal no longer undoes pointer
or scrollbar scrolling when focus is unchanged.
- Polished the native interface with themed common controls, clearer section hierarchy, a dedicated
status card, and a fixed Start/Stop/Save footer that remains visible while settings scroll.
- Confined the native scrollbar track to the settings viewport, aligned Tab and Shift+Tab with visual
order (including the fixed footer's Start, Stop, Save sequence), transferred keyboard focus to the newly enabled
Start/Stop action after session changes, re-revealed a still-focused setting after resize or DPI
reflow, and adapted stacked controls to unusually narrow work areas.
### Changed
- Documentation now describes the implemented first stable release rather than the original foundation stub.
- Motion distance remains a multiplier, while Normal, Circle, and Linear now use independently
designed IdleHarbor paths that preserve bounded safe-anchor restoration.
### Fixed
- Stop safely if the requested genuine-input observer cannot be refreshed, and bound its watchdog
cadence to avoid unnecessary hook churn.
- Recover a lost notification-area icon or keep the settings window visible.
- Preserve unowned settings directories during `-PurgeData` and validate the least-privilege Task
Scheduler principal on a non-mutating packaging test path.
- Refuse to overwrite foreign scheduled tasks, Startup-folder shortcuts, or HKCU Run values that
happen to use the IdleHarbor name.
- Report partial input cleanup failures and keep forwarded status/minimize commands bounded and visible.
- Establish the current lock and disconnect state before starting, and fail closed when Windows
cannot establish requested battery or session safeguards.
- Preserve and display every settings-recovery warning, keep the window visible and stopped, and
block automatic starts until recovered values are reviewed and saved.
- Defer every forwarded command outside `WM_COPYDATA`, preflight startup ownership before installer
mutations, and create the settings ownership marker before writing user data.
- Reject release tags that disagree with embedded versions, emit the required SPDX SHA-1 file and
package-verification values, and keep documented INI examples directly copyable.
- Route wheel input over child controls into the settings viewport, retain precision-wheel partial
deltas, follow Windows wheel preferences, and preserve native behavior for open combo lists.
- Roll back fresh-install files on failure, validate the application manifest version, require a
tracked licence before publication, and document release-directory trust assets.
- Keep the v0.1.0 publication lane stable-only by rejecting prerelease and build-metadata tags
consistently in both workflow and source-version validation.
- Pass the triggering release tag through step-local environment data so PowerShell packaging and
GitHub release publication do not interpolate the tag directly into run scripts.
- Restore managed files, marker bytes, and owned startup state after failed updates; preserve
pre-existing scheduler folders; and clean up installer-created empty task folders.
- Reject linked managed files before an update can write outside its ownership boundary, and make
packaging/checksum verification pass under both Windows PowerShell 5.1 and PowerShell 7.
- Retain an exact-path transaction recovery backup when managed-file rollback is incomplete, clean
it up after a complete rollback, and reject first-time same-directory installs without a valid
ownership marker.
- Keep a redundant Stop request from moving focus when no session transition occurred.
- Size the settings body from the scroll viewport's effective client width, including wider native
scrollbars, so stacked and fill-width controls remain within the visible viewport.
- Recompute and republish the settings scroll range when scrollbar appearance changes the effective
viewport layout, keeping the bottom controls reachable after a breakpoint reflow.
- Re-evaluate a scrollbar-free viewport candidate after height-only resizes so an inherited vertical
scrollbar does not keep a tall, column-fit window in the narrow stacked layout.
- Preserve the requested scroll position through re-entrant scrollbar/layout probing and clamp it
only after the final stable viewport state is known.
- Serialize concurrent PowerShell packaging suites with a bounded, abandoned-owner-safe test lock
while preserving transaction-residue assertions.
- Use in-process .NET hashing for SBOM and checksum generation so concurrent Windows PowerShell
5.1 and PowerShell 7 packaging runs do not depend on command auto-loading.
- Repaint the settings viewport and all descendant controls after scrolling, layout convergence,
and Running/Stopped enabled-state changes so stale control fragments do not survive until resize.
- Clear newly exposed parent and footer pixels after viewport resize so clipped settings never
obscure the fixed Start/Stop/Save actions.
- Mark profile defaults and recovered settings as unsaved until explicitly saved, expose that state
to accessibility APIs, and keep all three footer actions separated at narrow high-DPI sizes.
- Keep first-owner and forwarded command-line overrides consistently available for explicit saving
without silently changing the persisted INI baseline.
- Preserve the unsaved-state prefix in notification-area tooltips and accessible status text while
recovering from a missing tray icon.
- Resolve the release-version source root after PowerShell parameter binding so the default release
checks run under both Windows PowerShell 5.1 and PowerShell 7.
- Keep the packaging test's deterministic scheduled-task shim isolated from the real per-user
ScheduledTasks module and any installed IdleHarbor task.
### Distribution
- Published under `GPL-3.0-only` as unsigned x64 and ARM64 portable archives
accompanied by SHA-256 checksums, per-architecture SPDX SBOMs, and GitHub artifact attestations.
[Unreleased]: https://github.com/Chris0Jeky/IdleHarbor/compare/v0.2.0...HEAD
[0.2.0]: https://github.com/Chris0Jeky/IdleHarbor/releases/tag/v0.2.0
[0.1.0]: https://github.com/Chris0Jeky/IdleHarbor/releases/tag/v0.1.0