From e28502c9a1c10749b640dccaf76f97bf4705fc03 Mon Sep 17 00:00:00 2001 From: Geoffrey Vancoetsem <10533139+geeooff@users.noreply.github.com> Date: Fri, 18 Sep 2026 19:15:11 +0200 Subject: [PATCH 1/4] Tick what 0.2.0 closed in the lots Lot 14 is done: the changelog, the notes script, the rules, v0.1.0 rewritten, 0.2.0 published with it. Lot 13 shipped in 0.2.0 and closes on the first update from it. Lot 8's chain ran twice; the second machine stays the maintainer's to report. Co-Authored-By: Claude Opus 5 --- docs/design/08-distribution.md | 6 ++++-- docs/design/13-updating.md | 6 ++++-- docs/design/14-release-notes.md | 17 +++++++++-------- docs/design/README.md | 4 ++-- 4 files changed, 19 insertions(+), 14 deletions(-) diff --git a/docs/design/08-distribution.md b/docs/design/08-distribution.md index 37fcd58..c76fe21 100644 --- a/docs/design/08-distribution.md +++ b/docs/design/08-distribution.md @@ -17,9 +17,11 @@ install on a second machine. the checklist, build the **MSI** and the **zip archive**, and publish a GitHub Release carrying both with their SHA-256 — nothing built or uploaded by hand. Written 2026-09-17 (`release.yml`, `scripts/release-notes.ps1`); - first run 2026-09-18 on the `v0.1.0` tag, green, three assets published + first run 2026-09-18 on the `v0.1.0` tag, green, three assets published; + second run the same day on `v0.2.0`, with the notes from the changelog + ([Lot 14](14-release-notes.md)) - [x] The documentation: *Getting started* and the README point at the release rather than at `cargo build`, the reference gains `purge`, *How it works* gains removal — 2026-09-17 -- [ ] Verified in the field: the MSI on two machines, one real upgrade, one purge round trip — the maintainer's machine done 2026-09-17/18, below: install, upgrade, uninstall, purge; the second machine's first install still to come +- [ ] Verified in the field: the MSI on two machines, one real upgrade, one purge round trip — the maintainer's machine done 2026-09-17/18, below: install, upgrade, uninstall, purge, and the 0.1.0 → 0.2.0 upgrade through the updater; the second machine's first install is the maintainer's to run and to report **Done when** a tag alone produces a release a stranger can install from, and the two artefacts on it were built by the workflow from that tag's commit. diff --git a/docs/design/13-updating.md b/docs/design/13-updating.md index 9e2abe7..88fad5e 100644 --- a/docs/design/13-updating.md +++ b/docs/design/13-updating.md @@ -1,6 +1,7 @@ # Lot 13 — Updating -**Status: in progress since 2026-09-18; ships in 0.2.0.** Decided 2026-09-17 +**Status: in progress since 2026-09-18; shipped in 0.2.0 the same day.** +Decided 2026-09-17 to be a lot of its own rather than a tail of [Lot 8](08-distribution.md): updating touches the "no network" non-goal, the tray menu and the running process, and each of those deserves its own measurement. The shape below @@ -16,8 +17,9 @@ meets the Restart Manager's dialog once, as recorded below. - [x] The zip copy updates itself the same way, through the after-exit shell — 2026-09-18, the script tested for its shape - [x] The documentation: *Getting started*, *How it works*, the reference, the README's word on the network — 2026-09-18 - [x] Measured on the maintainer's machine, 2026-09-18 13:03–13:33, both paths against the real `v0.1.0`: the handover mid-game and the resume, the check, the download and its verification, the install from the zip and from the package, the watcher back on the new version — below +- [x] Shipped: `v0.2.0`, 2026-09-18, the first version that carries the updater - [ ] Measured: offline and behind a proxy, as seen from the menu; the failure path restarting the old watcher; `/qn` on screen -- [ ] Verified in the field across a real release pair +- [ ] Verified in the field across a real release pair — the first update *from* 0.2.0, whenever the next release comes; that closes the lot **Goal.** A user who wants the newer version gets it from the notification icon, without a browser, without an administrator prompt, and without the diff --git a/docs/design/14-release-notes.md b/docs/design/14-release-notes.md index 9ebac70..8adeac2 100644 --- a/docs/design/14-release-notes.md +++ b/docs/design/14-release-notes.md @@ -1,17 +1,18 @@ # Lot 14 — Release notes people can read -**Status: in progress since 2026-09-18, the same day it was proposed**, on -the maintainer's remark after the first update ran through the menu: -*What changed in 0.1.0* opened the release page, and the page said *First -public release* over a list of commits. That is a changelog for the people -who wrote the commits, not for the person who clicked. Taken before 0.2.0, -so that release reads well from the moment it is published. +**Status: done 2026-09-18, the day it was proposed**, on the maintainer's +remark after the first update ran through the menu: *What changed in +0.1.0* opened the release page, and the page said *First public release* +over a list of commits. That is a changelog for the people who wrote the +commits, not for the person who clicked. Taken before 0.2.0, so that +release read well from the moment it was published — it did, and 0.1.0's +page was rewritten the same evening. - [x] `CHANGELOG.md`, with the sections for 0.1.0 and what 0.2.0 will carry — 2026-09-18 - [x] `release-notes.ps1` takes the section for the tag and refuses a version without one; `build.ps1 release` refuses it first, on the machine that can still write it — 2026-09-18 - [x] The rules of a section, in `AGENTS.md` — 2026-09-18 -- [ ] `v0.1.0`'s notes rewritten once with its section, on approval -- [ ] The first release published this way: 0.2.0 +- [x] `v0.1.0`'s notes rewritten once with its section, on approval — 2026-09-18, the platform line corrected with it +- [x] The first release published this way: 0.2.0 — 2026-09-18, the workflow's first run with a dated section, green **Goal.** Every release page reads, in a few lines, what changed for the person running the program — and the same lines are what the updater's diff --git a/docs/design/README.md b/docs/design/README.md index fafa4bb..b9e49b4 100644 --- a/docs/design/README.md +++ b/docs/design/README.md @@ -24,8 +24,8 @@ session rather than when the code compiles. Each has its own page. | 10 | [Configuration window](10-configuration-window.md) | proposed | | 11 | [Documentation for the people who use it](11-user-documentation.md) | done | | 12 | [Editing the configuration without breaking it](12-editing-on-a-copy.md) | proposed | -| 13 | [Updating](13-updating.md) | in progress | -| 14 | [Release notes people can read](14-release-notes.md) | in progress | +| 13 | [Updating](13-updating.md) | shipped in 0.2.0; closes on the first update from it | +| 14 | [Release notes people can read](14-release-notes.md) | done | **Dependency order:** 1 → 2 → 4 → 5 → 6 → 7, with 3 independent and 7 needing both 3 and 6. Logging sits before the icon deliberately — the icon logs too, From 7593269f0ddfe85fad1e0488c8f57ee185326f6d Mon Sep 17 00:00:00 2001 From: Geoffrey Vancoetsem <10533139+geeooff@users.noreply.github.com> Date: Fri, 18 Sep 2026 20:33:24 +0200 Subject: [PATCH 2/4] Say how to run the recipe's scripts where Windows refuses them A Windows PC out of the box runs no script, and marks anything downloaded; the recipe said .\install-tasks.ps1 and nothing more, which is where a person following it on a fresh machine stops. Unblock-File and a per-command Bypass change nothing on the machine and need no administrator; the elevated half already relaunches itself that way. Co-Authored-By: Claude Opus 5 --- docs/recipes/fancontrol-fan-profiles/README.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/docs/recipes/fancontrol-fan-profiles/README.md b/docs/recipes/fancontrol-fan-profiles/README.md index 6cdc29d..5ef6cec 100644 --- a/docs/recipes/fancontrol-fan-profiles/README.md +++ b/docs/recipes/fancontrol-fan-profiles/README.md @@ -113,6 +113,20 @@ both tasks. From any PowerShell window, in this folder: .\install-tasks.ps1 ``` +**If Windows refuses to run it** — *running scripts is disabled on this +system*, which is what a Windows PC says out of the box, and what it says +of anything downloaded — run it this way instead, which changes nothing on +the machine and needs no administrator rights: + +```powershell +Unblock-File .\*.ps1 +powershell -ExecutionPolicy Bypass -File .\install-tasks.ps1 +``` + +The first line removes the mark Windows puts on downloaded files; the +second lets this one command run scripts. The elevated part relaunches +itself the same way, so the whole chain goes through. + It asks for administrator rights itself — one prompt. On Windows 11 with `sudo` enabled in *inline* mode it carries on in the same window; otherwise a second window opens for the elevated part and waits for Enter before @@ -342,6 +356,9 @@ the same way the install script does: .\uninstall-tasks.ps1 ``` +Or, where Windows refuses scripts, `powershell -ExecutionPolicy Bypass +-File .\uninstall-tasks.ps1`, as for the install. + It removes the two tasks it knows — *FanControl Idle* and *FanControl Game* — and leaves everything else: FanControl and its configurations, the `\GameModeExecutor` folder in Task Scheduler with the watcher's own task in From 42e010f3773b9d5aa6b3eb14b7561f58de67fbcb Mon Sep 17 00:00:00 2001 From: Geoffrey Vancoetsem <10533139+geeooff@users.noreply.github.com> Date: Fri, 18 Sep 2026 22:46:35 +0200 Subject: [PATCH 3/4] Warn about SmartScreen and say the recipe's file replaces yours Two lines a first-time user was missing on the second machine: the installer is unsigned, so Windows stops it with "Windows protected your PC" and nothing said "More info, Run anyway"; and the recipe's page said to copy its config.toml "over your own", which was read as a merge when the file is the whole configuration and the starter has nothing to keep. Co-Authored-By: Claude Opus 5 --- docs/getting-started.md | 8 ++++++-- docs/recipes/fancontrol-fan-profiles/README.md | 6 +++++- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/docs/getting-started.md b/docs/getting-started.md index 206f46b..b919832 100644 --- a/docs/getting-started.md +++ b/docs/getting-started.md @@ -20,8 +20,12 @@ The `w` just means *windowless*, the same convention as `python.exe` and The release page offers two files that hold the same two executables. -**The installer, `GameModeExecutor-.msi`.** Run it. It asks for no -administrator rights and installs for you alone, into +**The installer, `GameModeExecutor-.msi`.** Run it. Windows may +stop you first with *Windows protected your PC*, because the installer is +not signed with a certificate it knows: *More info*, then *Run anyway*. The +release page lists the file's SHA-256 if you want to check what you +downloaded. It asks for no administrator rights and installs for you alone, +into `%LOCALAPPDATA%\Programs\GameModeExecutor`. It also writes a starter configuration if you have none, registers the logon task, and starts the watcher: the confirmation that it worked is the **grey controller icon** diff --git a/docs/recipes/fancontrol-fan-profiles/README.md b/docs/recipes/fancontrol-fan-profiles/README.md index 5ef6cec..408f17e 100644 --- a/docs/recipes/fancontrol-fan-profiles/README.md +++ b/docs/recipes/fancontrol-fan-profiles/README.md @@ -268,7 +268,11 @@ this does not work, nothing further will, and the problem is on this side. ## 5. The configuration -Copy [`config.toml`](config.toml) over your own. It is the complete file: +Replace your `config.toml` with [this one](config.toml): copy it over, +whole, rather than merging the two — the starter file the installer wrote +has nothing in it worth keeping. Only if you already run commands of your +own should you add these two actions to your file instead. It is the +complete file: ```toml [general] From 63c6c15d3863ffaa7d2c9e9ed534b6a8a9a6c75a Mon Sep 17 00:00:00 2001 From: Geoffrey Vancoetsem <10533139+geeooff@users.noreply.github.com> Date: Fri, 18 Sep 2026 22:46:35 +0200 Subject: [PATCH 4/4] Record what the second machine's first install taught Lot 8's last field box: 0.2.0 installed on the second machine on 2026-09-18, the log showing the three setup lines, the watcher starting, and two sessions. The record keeps the five frictions a first-time user met around the package, with what was taken at once (SmartScreen line, execution policy, replace-not-merge) and what is only proposed (a recipes artefact on the release, a Start menu shortcut). Lot 9 gets the third refinement observation: a session named chrome.exe by Windows' own list, renamed Overwatch.exe at 3 % on its loading screen. Co-Authored-By: Claude Opus 5 --- docs/design/08-distribution.md | 67 ++++++++++++++++++++++++++++++++-- docs/design/09-robustness.md | 9 +++++ 2 files changed, 72 insertions(+), 4 deletions(-) diff --git a/docs/design/08-distribution.md b/docs/design/08-distribution.md index c76fe21..fdd1291 100644 --- a/docs/design/08-distribution.md +++ b/docs/design/08-distribution.md @@ -4,9 +4,9 @@ workflow alone, from the tag's commit, with the installer, the zip and their checksums — which is the "done when" below. The lot was taken 2026-09-17/18 in the order listed; `scripts/build.ps1` was written first on purpose, since -a release that cannot be made by hand is not one CI can make either. One -field check is still outstanding and is recorded when it happens: the first -install on a second machine. +a release that cannot be made by hand is not one CI can make either. The +last field check, the first install on a second machine, came in on the +evening of 2026-09-18 with its log; what it taught is below. - [x] Create the public GitHub repository and push — done 2026-09-17, with approval - [x] The three measurements below, on a minimal package, before any table is written — done 2026-09-17 @@ -21,7 +21,7 @@ install on a second machine. second run the same day on `v0.2.0`, with the notes from the changelog ([Lot 14](14-release-notes.md)) - [x] The documentation: *Getting started* and the README point at the release rather than at `cargo build`, the reference gains `purge`, *How it works* gains removal — 2026-09-17 -- [ ] Verified in the field: the MSI on two machines, one real upgrade, one purge round trip — the maintainer's machine done 2026-09-17/18, below: install, upgrade, uninstall, purge, and the 0.1.0 → 0.2.0 upgrade through the updater; the second machine's first install is the maintainer's to run and to report +- [x] Verified in the field: the MSI on two machines, one real upgrade, one purge round trip — the maintainer's machine done 2026-09-17/18, below: install, upgrade, uninstall, purge, and the 0.1.0 → 0.2.0 upgrade through the updater; the second machine's first install, 0.2.0, done 2026-09-18 in the evening by the maintainer and reported with the log, below **Done when** a tag alone produces a release a stranger can install from, and the two artefacts on it were built by the workflow from that tag's commit. @@ -245,6 +245,65 @@ worked, and four remarks came back, all taken the same evening: tunnels a creation time across a delete-and-recreate seconds apart, so it read as the build from the day before. +## What the second machine taught + +The maintainer installed 0.2.0 on the second machine on the evening of +2026-09-18, the way anyone would: the installer downloaded from the release +page with Chrome, the recipe folder fetched from GitHub, *Getting started* +and the recipe's page followed on a machine that had never seen the +program. The log came back with five remarks. + +The log first. The three `setup` lines within 300 ms of each other at +20:27:57 — *Starter configuration written*, *Logon task registered*, +*Watcher started through its task* — then *0.2.0 (f33cb006) starting*; a +*Quit* at 20:43 once the recipe's configuration was in, and the task run +by hand from Task Scheduler sixteen seconds later; a first session, +`cs2.exe`, eighteen minutes; a second one named `chrome.exe` first and +`Overwatch.exe` twenty-one seconds later, on which +[Lot 9](09-robustness.md#stop-timing-the-refinement) has the note. The +package did on that machine what it had done on this one, which closes +the field box above. + +The remarks are the friction a first-time user meets *around* the package +rather than in it. None needed an action that night; they are recorded so +the next lots can weigh them, with what was taken at once and what is +only proposed: + +- **SmartScreen stopped the installer.** Expected — code signing is + declined below, with the reasons — and *More info*, then *Run anyway*, + gets through; but nothing had said so. *Getting started* now does, in a + line beside the checksum, taken 2026-09-18. +- **Windows refused the recipe's scripts:** the default execution policy, + plus the mark Chrome puts on a downloaded file. The recipe's page now + gives the two lines that get past it without changing the machine + (`Unblock-File`, then `-ExecutionPolicy Bypass` for the one command), + taken 2026-09-18; `elevate.ps1` already relaunched its elevated half that + way. A `.cmd` beside each script, running it with that switch, would + spare the typing altogether — proposed, weighed with the next point. +- **GitHub offers no way to download one folder.** The recipe was reached + by downloading the whole repository as a zip and digging the folder out + of it. The release could carry the recipes as a third artefact, + `GameModeExecutor-recipes-x.y.z.zip`, built by the same workflow from + the same commit and linked from `README.txt` — files to run, not pages + to read, so the argument in + [Documentation is linked, not shipped](#documentation-is-linked-not-shipped) + does not hold against it. Proposed, not decided. +- **The configuration was merged rather than replaced.** The recipe's + `config.toml` is the whole file and the starter one has nothing worth + keeping, but the page said *copy over your own*, which someone careful + reads as a merge. It now says to replace the file whole, and when + merging is the right thing instead — taken 2026-09-18. +- **Starting it again after a change to the configuration.** *Quit* is one + click; starting the watcher again meant Task Scheduler, and a first-time + user does not know the task is there. Two answers, not exclusive: live + reload, designed in + [Lot 9](09-robustness.md#configuration-faults-shown-where-the-program-already-lives), + makes the restart unnecessary; and a Start menu entry from the package — + a `Shortcut` row to `gamemode-executorw.exe`, which starts the watcher + or does nothing if one is running — gives *Quit* an obvious undo. The + shortcut is a package change and would go with the recipes artefact if + that is taken; the reload is the next lot's. + ## Versioning Decided 2026-09-17, when the question came up before publication: why the diff --git a/docs/design/09-robustness.md b/docs/design/09-robustness.md index 4a6d05e..c2f9b21 100644 --- a/docs/design/09-robustness.md +++ b/docs/design/09-robustness.md @@ -159,6 +159,15 @@ or the counters cannot be read. Each bail-out spends the one attempt. Two Battlefield 6 sessions an hour apart lost it and won it: the second read 0.0 % for every candidate at T+10 s and 75 % at T+20 s. A margin, not a calibration. +A third session, on the second machine on 2026-09-18 at 21:15, shows the +other side of the lottery. Windows' per-user list there carries `chrome.exe` +— the list grows with whatever the Game Bar was once used over, as far as +this record understands it — so the session was named after Chrome first, +and the one attempt at T+21 s read `Overwatch.exe` at 3 %, a loading +screen's worth, and renamed it. Enough that time; had the game rendered +nothing yet at T+21 s, the session would have stayed *chrome.exe* to the +end, in the log and in the placeholders. + Two changes worth weighing, in order of appetite: - **Only count an attempt that reached a verdict.** "Nothing is rendering yet"