Lot 13: updating — check, download, verify and install from the icon - #5
Merged
Merged
Conversation
The page records what was decided on 2026-09-18 before any code: the installer is the updater and the package already stops and restarts the watcher; the zip copy updates itself through the after-exit shell; the session is handed over rather than closed, with stop --handover and a start that resumes an open session; the state machine the menu renders, its phases, entries and two expiries; the faults and their log lines; what it does not defend against; and what to measure. AGENTS.md gains the three rules the lot rests on: the tray renders state and holds no rule, the setup commands are a contract with three callers verified together, and the one network connection is the user's click. The non-goal and the README say the same. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
A stop mid-game meant Quit: the stop commands ran, the marker went, and the watcher that followed detected the game again and ran the start commands -- the idle and then the gaming configuration two seconds apart, in the middle of a game. An update or an upgrade needs a stop that leaves the session open instead. StopSignal carries a reason. `stop --handover` posts WM_HANDOVER to the session window where WM_CLOSE means Quit; the engine then runs nothing and leaves the marker saying the session is open. At start, the engine looks for the presence writer before recovering: still running, the session is resumed from the marker -- name, icon, the wait on the writer -- with neither start nor stop commands run; gone, the recovery of before. Three scenarios in engine/tests.rs. The package's one stop action becomes two: StopForUpgrade hands over, since RegisterTask starts the new watcher seconds later, and StopForRemoval restores, since nobody follows an uninstall. The installed 0.1.0 does not know the flag, so the first upgrade from it gets the Restart Manager's dialog back once, accepted and recorded. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
`update` is the object the menu renders and holds no rule of its own: phases, events, the items each phase shows and the two expiries live in `Machine`, tested whole through events. The network is behind `Feed` -- the latest release's redirect, a text file, a download -- with WinHTTP as the one real feed; the hash is CNG's SHA-256. What the release answers was measured by hand against v0.1.0 through the code itself, and what the tests exercise instead is a listener of their own on 127.0.0.1, written from the standard library, answering the record's table: the 302 with the tag, a redirect to a second listener for the asset host, a body larger than one read, a cut-off download, a 404, a 503, a page where a text file should be, a port nobody listens on. It talks plain http to a cfg(test) constructor the shipped program does not have; TLS is WinHTTP's, and a bad certificate was measured refused with 12175. No test calls an external host, and AGENTS.md says so. Two things the record could not know: closing a WinHTTP session cancels the requests under it, so the parent handles ride along with the response; and a header is asked for its length first, since a signed asset URL runs to a kilobyte. An installed copy runs the package quietly through a hidden shell and lets the package hand this watcher's session to the new one; an unpacked copy's shell waits for this process, expands the archive over the folder with the old executables kept as .old, and runs install-task. A copy counts as installed only when the upgrade code is registered and it runs from the folder the package installs to, so an unpacked copy beside a package updates itself rather than the package. pending.txt and result.txt tell the next watcher whether the update took. What Windows Installer knows about the program moves to `package`, which purge and update both ask. The tray draws the section from update::view() and hands a chosen entry back; `gamemode-executor update [--check]` drives the same object from a console. Every step is logged under `update`. The library's line coverage goes from 64.5 % to 70 % with the updater at 77 % to 95 % per file and the command line at 44 % from nothing. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…p the same four files What the first field run of the updater taught, both paths against the real v0.1.0. The menu closes on the click, as every Windows menu does, and the verdict waited in a menu nobody had reopened: the outcome of what the user clicked now reaches them as a silent notification from the icon, held back during quiet hours, and stays in the menu too. The object owns it -- Machine leaves a Notice on each outcome and the tray draws it -- and it only ever answers a click. A 0.0.9 build installed after a 0.1.0 that did not know pending.txt reported the update failed when it had not: settle now reads Windows Installer's own verdict from the log it wrote, UTF-16 with a byte-order mark, and says installed, or names the installer's error code, before falling back to "did not take". The resume line carried a run of spaces where a line continuation had been meant; fixed. The package carried the license and two executables, the zip a readme and the whole documentation tree: both now carry the same four files, LICENSE.txt and README.txt beside the executables, one readme for both ways in that links the documentation and the recipes for this exact commit. Lot 14, release notes people can read, is proposed on the maintainer's remark that the release page says nothing to the person who clicked What changed. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The agent, from the commits and the design record, on request; the workflow publishes a placeholder it cannot fill; the rules of the summary go in AGENTS.md before anyone follows them twice. Left open in Lot 14 until it is taken. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
… when asked The install goes by in a second on a fast machine, too quick to see the version change: the version that comes out of it now says so with one more notification at its first start, from the pending file the previous watcher wrote. A watcher the package itself starts decided at start whether it was an installed or an unpacked copy -- and RegisterTask runs before RegisterProduct, so at that instant Windows Installer knows no product. On the second field run of the package path it took itself for an unpacked copy, fetched the zip and expanded it over the package's own folder. The kind is now decided when the question is asked, from what Windows Installer says at that moment; the tests pin it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The version that comes out of an update says it runs at its first start, from the pending file the previous one wrote. A notice for the install step itself, shown for an afternoon, was one too many: one notification for the outcome, not two for the steps. The published 0.1.0 predates the pending file, so the field runs ended on no notification; the first real release pair will show the new one. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The package header counts five actions, not four; the updater's module doc names check_now as the one connection rather than the menu's action; the user agent carries the bare version; how-it-works lists the updates folder among the places; the lot page says it ships in 0.2.0 and closes on the first update from it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The notes claimed Windows 10 and 11. Windows 11 is where every measurement in the record was taken; Windows 10 ships the same Xbox Game Bar component since 1903 and should work, and the notes now say exactly that rather than more. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Lot 13, updating: a newer release is found, fetched, verified and installed from the notification icon — or from
gamemode-executor update— with the game session handed from the old watcher to the new one. Design record indocs/design/13-updating.md; the shape was agreed before a line was written and corrected in place where the field said otherwise.stop --handoverpostsWM_HANDOVERwhereWM_CLOSEmeans Quit; the engine runs nothing and leaves the marker open, and the next watcher looks for the presence writer before recovering: still running, it resumes the session — name, icon, the wait on the handle — with neither start nor stop commands run. Three scenarios inengine/tests.rs; measured mid-game with Starfield on both install paths. The package's one stop action becomes two:StopForUpgradehands over,StopForRemovalrestores.updateis the object the menu renders and holds no rule of its own: phases, events, the items each phase shows and the two expiries live inMachine, tested through events. The network is behindFeed— the latest release's redirect, a text file, a download — with WinHTTP as the one real feed and, in the tests, a listener of their own on127.0.0.1from the standard library answering the record's table. No test calls an external host, and AGENTS.md says so. The hash is CNG's SHA-256; a bad certificate was measured refused (12175); the network path was measured by hand againstv0.1.0and is repeated withupdate --check..old, and runsinstall-task. A copy counts as installed only when the upgrade code is registered and it runs from the package's folder — decided when asked, not at start, since the package starts the watcher before it registers the product (that one bit a field run and was replayed clean).pending.txt,result.txtand Windows Installer's own log tell the next watcher whether the update took.LICENSE.txt,README.txt— with one readme for both ways in that links the documentation and the recipes for the exact commit. What Windows Installer knows about the program moves topackage, whichpurgeandupdateboth ask.Field verification, 2026-09-18
On the maintainer's machine, from a
0.0.9build of this branch against the realv0.1.0: zip path and package path, each with the handover mid-game, the check, the download and its verification, the install, and the watcher back on 0.1.0 within a second; the notifications seen on screen, the first-start one with a planted pending file. What waits for the first real release pair: the chain where one version writes the pending file and the next reads it — the lot stays in progress until an update runs from 0.2.0.One degradation, accepted and recorded: the installed
0.1.0does not know--handover, so the upgrade from it gets the Restart Manager's dialog once, on the two machines that have it.Test plan
.\scripts\build.ps1 test— 165 + 4 tests, 25 pages, every link resolves; line coverage 64.5 % → 70 %.\scripts\build.ps1 release— 102 ICEs clean, both artefacts carry the four filesThe version bump to 0.2.0 comes on its own
release/0.2.0branch after this merges, per the release procedure.🤖 Generated with Claude Code