Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 66 additions & 5 deletions docs/design/08-distribution.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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.
Expand Down Expand Up @@ -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
Expand Down
9 changes: 9 additions & 0 deletions docs/design/09-robustness.md
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
6 changes: 4 additions & 2 deletions docs/design/13-updating.md
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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
Expand Down
17 changes: 9 additions & 8 deletions docs/design/14-release-notes.md
Original file line number Diff line number Diff line change
@@ -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
Expand Down
4 changes: 2 additions & 2 deletions docs/design/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
8 changes: 6 additions & 2 deletions docs/getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -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-<version>.msi`.** Run it. It asks for no
administrator rights and installs for you alone, into
**The installer, `GameModeExecutor-<version>.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**
Expand Down
23 changes: 22 additions & 1 deletion docs/recipes/fancontrol-fan-profiles/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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]
Expand Down Expand Up @@ -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
Expand Down