diff --git a/docs/design/08-distribution.md b/docs/design/08-distribution.md index 37fcd58..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 @@ -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 +- [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. @@ -243,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" 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, 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 6cdc29d..408f17e 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 @@ -254,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] @@ -342,6 +360,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