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
44 changes: 34 additions & 10 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,16 @@ These decide most questions before they are asked.
option first and argue for a fallback only if it protects something
concrete.
- **Discreet.** No dialogs, no windows, no sounds. The icon, its tooltip and
its menu are the whole user interface; the log is the rest.
- **No elevation, no network, no service, no telemetry.** Recorded as
non-goals in the design record with their reasons. Programs that need
administrator rights are reached through a scheduled task the user registers
once, never by elevating the watcher.
its menu are the whole user interface, plus a silent notification to
answer something the user clicked -- a menu closes on a click, as every
Windows menu does, and the answer has to reach them somewhere; the log is
the rest.
- **No elevation, no service, no telemetry, and no network the user did
not ask for.** Recorded as non-goals in the design record with their
reasons. The one connection the program ever opens is *Check for updates*,
on a click, and `docs/design/13-updating.md` says exactly what it sends.
Programs that need administrator rights are reached through a scheduled
task the user registers once, never by elevating the watcher.
- **Microsoft libraries only.** The `windows` crate for Win32, the Windows
SDK's `rc.exe` for resources. No third-party tray, icon, or installer crate.

Expand All @@ -60,10 +65,23 @@ deleted.
`ALL CAPS` categories, no `camelCase` in prose. Conversation with the
maintainer is in French.
- **Log lines follow the contract in `docs/reference.md`.** `info` is
reserved for detection, the watcher's own start and stop, and what the
setup commands did to the machine; everything else is `debug` unless it is
a degradation (`warn`) or needs the user (`error`). The message is the sentence, the fields are the technical annex,
and every call names a `target:` — a test fails the build otherwise.
reserved for detection, the watcher's own start and stop, what the setup
commands did to the machine, and each step of an update; everything else
is `debug` unless it is a degradation (`warn`) or needs the user
(`error`). The message is the sentence, the fields are the technical
annex, and every call names a `target:` — a test fails the build
otherwise.
- **The tray renders state and holds no rule.** What the icon, the tooltip
and the menu show comes from objects that own the rules — the engine's
session, `update`'s phase — and the tray asks them what to draw and which
action a click means. A rule written in the menu code is in the wrong
place and cannot be tested.
- **The setup commands are a contract with three callers.** `stop`, `init`,
`install-task` and `uninstall-task` are sequenced by the package
(`scripts/msi.ps1`), by the zip's after-exit shell in `update`, and by
`purge`, each in the order its own mechanism allows. A change to any one
of those commands, however small, is verified on all three paths before
it is called done.
- Module-level doc comments carry the rules a module is shaped by (the tray's
re-entrancy rule, the marker's location, the engine's callback). Read them
before changing a module, and update them when the rule changes.
Expand All @@ -76,7 +94,13 @@ deleted.
- Pure logic gets a unit test; Win32 behaviour gets verified by hand and the
result written into the design record with its date. The engine reads the
OS only through `sensor::Sensor`, and `engine/tests.rs` scripts one to run
whole sessions; a change to the loop gets a scenario there.
whole sessions; a change to the loop gets a scenario there. The updater
reads the network only through `update::feed::Feed`, scripted the same
way.
- **No test calls an external host**, ignored or not: the script runs the
ignored tests on every developer machine, and a test that needs GitHub
is a test that fails with the Wi-Fi. The network path is measured by hand
with `gamemode-executor update --check` and recorded with its date.
- Commit messages: an imperative subject, a short body saying what changed
and why, and a `Co-Authored-By` trailer for the agent that co-wrote it. The
collaboration is not hidden.
Expand Down
4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ windows = { version = "0.62", features = [
# MsiEnumRelatedProducts: whether the installer owns the executables, which
# decides how `purge` removes them.
"Win32_System_ApplicationInstallationAndServicing",
# The updater: WinHTTP for the release, CNG for the SHA-256 of what it
# fetched. Microsoft's libraries, no HTTP or hashing crate.
"Win32_Networking_WinHttp",
"Win32_Security_Cryptography",
# WNDCLASSEXW names HBRUSH, HICON and HCURSOR, so the window class needs Gdi
# even though this program never draws anything.
"Win32_Graphics_Gdi",
Expand Down
12 changes: 7 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ or anything else with a command line.
**There is no list of games to maintain.** Windows itself decides when a game
is running — the watcher observes the Game Bar presence writer that Windows
starts for one — and it does not poll while you play. It runs as you, with no
administrator rights, keeps no network connection, and shows nothing but a
small icon in the notification area.
administrator rights, connects to nothing unless you ask it to look for an
update, and shows nothing but a small icon in the notification area.

## Documentation

Expand Down Expand Up @@ -58,9 +58,11 @@ gamemode-executor init # write the starter config.toml
gamemode-executor install-task # start the watcher now and at every logon
```

To remove it, *Programs and Features* takes the executables and the logon
task away and leaves your configuration; `gamemode-executor purge` removes
every trace. Building
Later releases install themselves: right-click the icon, **Check for
updates**, and the menu offers the newer version — nothing is checked
unless you ask. To remove it, *Programs and Features* takes the executables
and the logon task away and leaves your configuration; `gamemode-executor
purge` removes every trace. Building
from source is in the [reference](docs/reference.md#building-and-releasing).

## License
Expand Down
11 changes: 11 additions & 0 deletions docs/design/08-distribution.md
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,17 @@ worked, and four remarks came back, all taken the same evening:
later logged *Logon task registered* with the user, the program, the
configuration path and the 15 s delay — the first time that line, rather
than *kept*, had been seen from the package.
- **The same four files in both, decided 2026-09-18** on the maintainer's
remark that the package carried the license and two executables while
the zip carried a readme and the whole documentation tree besides. Now
both carry `gamemode-executor.exe`, `gamemode-executorw.exe`,
`LICENSE.txt` and `README.txt` — `.txt` both, because the people who open
them are not on GitHub; the repository keeps `LICENSE` without an
extension, as GitHub expects, and the staging step renames it. The readme
is one text for both ways in, and links the documentation and the recipes
*for this exact commit* instead of shipping a copy that could describe a
version no longer running. `purge` still knows the old zip's `LICENSE`
and its `docs\` tree.
- **The package's own metadata.** Explorer's Details tab showed *Title:
Installation Database* — the phrase the SDK suggests, which tells a tool
what the file is and a person nothing. The summary now names the product
Expand Down
21 changes: 21 additions & 0 deletions docs/design/09-robustness.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,16 @@ depend on Windows' timing:
- At start, before watching, a marker present means the last session never
closed: one `info` line naming the game, the stop commands, the marker
removed. Logoff, shutdown, crash and power cut are one case.
- **Since 2026-09-18, the writer is looked for first.** A marker present
with the presence writer still running means the game never ended: the
last watcher handed the session over — `stop --handover`, which an update
or an upgrade uses because a watcher follows within the second — or died
under it. Then nothing runs, neither stop nor start, and the session is
resumed from the marker: name, icon, the wait on the writer's handle. The
stop commands run at the end of the game as they always did. Without this
an update mid-game switched the configuration off and on again two
seconds apart. Three scenarios in `engine/tests.rs`; the design is in
[Lot 13](13-updating.md).

**Where it lives, and why not in `logs\`.** A logs folder is disposable by
nature and gets emptied without a second thought, which would take a pending
Expand Down Expand Up @@ -202,3 +212,14 @@ game", so the icon stayed grey through such a session. The sink now carries
a `Session` enum — `Idle` or `Playing(Option<GameSignal>)` — and the case
has a test. The manual `trigger` command no longer builds an engine at all;
it runs the commands, which is all it ever did.

**Measured again on 2026-09-18, with Lot 13's updater in:** the library at
70 % line coverage, ignored tests included, and `winhttp` at 92 % through a
listener the tests run themselves. The updater was written to the
same cut — the network behind `Feed`, the machine driven by events — and
sits at 76 % to 95 % per file, the shell scripts it generates checked for
their shape and the `pending`/`result` files exercised on scratch folders.
The command line gained parse tests and a machine-bound diagnostics test,
44 % from nothing. What stays near zero is what it should be: `service`,
`win`, and the parts of `tray` that are Win32 calls, verified by hand with
the dates in this record.
Loading