Lot 15: detect the games marked by hand, and make the idle look cheap - #10
Merged
Merged
Conversation
Death Stranding 2, marked "Remember this is a game" days earlier, ran for an hour on 2026-09-20 with the watcher silent: Windows recorded the game (LastGameActivity and the entry's LastAccessed three seconds after the launch) and never started the presence writer. Its list entry has Revision 1 and no Xbox TitleId, where every title the watcher has ever detected carries the distributed revision and a TitleId; the writer is presence, and a title named by hand has none to write. The detection page keeps the figures and corrects its promise in place; How it works and Getting started say what the toggle does and does not do for this program. Lot 15 proposes reading Windows' own list as a second signal -- at launch and at the tick mid-game, on a registry change notification rather than a poll -- with the measurements to make first. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Lot 15's first box. `presence-probe watch-games` parks on a registry change notification over Windows' game list and says, at each wake, which entry was added, removed, or had its LastAccessed moved, labelled hand-made or listed, with the presence writer logged beside it. An optional key lets the probe be checked on a key one can write to; done on a scratch key under HKCU\Software, which also showed that an entry created with its values arrives as two notifications. `registry::Key` gains a QWORD reader and its raw handle for the one call the wrapper does not cover. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The maintainer played five titles with the probe watching. DS2 and Wreckfest 2 were in Microsoft's list all along: unticked and relaunched, each got a new entry from the distributed list (Revision 2691, a TitleId) and the presence writer started. The hand-made entry had been shadowing Microsoft's. The Other Side, not listed, stayed unseen. So the class splits: titles ticked before Microsoft listed them, which unticking brings back today -- said now in How it works and Getting started -- and titles Microsoft does not list, which only Lot 15 reaches. Windows writes the game's entry at every launch, listed or not, within the same quarter-second as the writer. But the registry notification never woke the probe through those writes; the probe now arms once per wake and reads the list every 250 ms to log any change that arrives without one, for a second run. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Seven writes to Windows' game list -- Starfield's launch, three launches of The Other Side, an untick and a tick mid-game -- and not one change notification; the probe found each by reading the list every 250 ms. The lot's plan to park on RegNotifyChangeKeyValue is contradicted in place, and replaced by what the runs decide: no new polling -- the second signal reads the process snapshot the idle poll already takes, matching hand-made entries by exact path -- and the list is read again only when its key's last-write time moves, which a tick or an untick does. Three measurements left before building. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
`presence-probe cost` times the idle poll's steps over 300 rounds: the process snapshot the poll already takes is about 4 ms, the hand-made entries' names compared against it 13 us, the list key's last-write time 11 us, and a full-path query, paid only for a name that matches, 55 us. The second signal adds about 25 us to a 4 ms poll and nothing that wakes the watcher. FanControl, elevated through its task, granted SYNCHRONIZE and the limited query to an unelevated reader, so an elevated game can be waited on. The measurements box of Lot 15 is ticked; the untick mid-game is left to the field run. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
On the maintainer's question -- was the notification the wrong one, or asked the wrong way? -- `presence-probe watch-methods` armed eight RegNotifyChangeKeyValue variants at once: through HKEY_USERS\<sid>, through RegOpenCurrentUser, without the subtree, on the parent key and on all of HKCU\System with every filter, on each entry on its own, and synchronously on a blocking thread. A ninth, WMI's RegistryTreeChangeEvent, ran from an unelevated PowerShell. Across a Starfield launch and a tick and untick of The Other Side, WMI fired for every write, as it happened; the eight fired once between them, the removed entry waking its own handle. The record keeps the table and the WMI provider's cost as far as an unelevated reader can see it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The maintainer set WMI aside until the reason is known and asked for the literature. Microsoft's page for RegNotifyChangeKeyValue says it cannot see changes made by RegRestoreKey; Raymond Chen explains why a deleted key ends its notifications, which accounts for the removed entry and not for Starfield; WindowsAppSDK issue 4075 reports the same silence the other way round, for a packaged reader. Two documented mechanisms fit -- a restore, or a write through a packaged app's merged registry -- and neither is confirmed; Process Monitor would show which. Asked whether a longer interval would spend less: the probe's `cost` now times K32EnumProcesses, the process ids alone, at 32 us against the Toolhelp snapshot's 4 ms. A poll that names only processes it has not seen would cost about 50 us, so the interval need not move; process id reuse is the risk to measure first. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Process ids: Microsoft documents that an id is unique only while its process lives and can be reused after, and Raymond Chen that the id lasts as long as the process object -- running, or held by a handle. Nothing documents how soon; a spike of 400 short processes at fifty a second saw ids come back after 2.8 s at the soonest, never within 2 s. So the idle poll lists the ids alone, names only processes it has not seen, and keeps a full snapshot every thirty seconds as the net for a reused id: about 0.016 % of a core at two seconds against 0.2 % today. The hint the maintainer asked for: Microsoft's list is the undocumented KnownGameList.bin under the local profile; matched as whole fields -- the executable's name and its folder -- it knows DS2 and Wreckfest 2 and not chrome.exe, and the GUIDs it carries are those of the entries Windows created from it. At start, each hand-made entry it covers gets one info line saying the box can be unticked; a file that does not parse as described gives no hint. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Lot 15's program side. The idle look now answers a Sighting: the presence writer, or a process whose full path is a hand-made entry of Windows' game list (Revision 1, no TitleId) -- the titles for which Windows never starts the writer. The engine parks on either's handle; a game marked by hand is not refined, its entry names it exactly. The list is read again only when its key's last-write time moves, so a tick mid-game becomes a session at the next look; an untick takes effect at the next launch, since noticing it would mean waking during the game. The look itself costs a twelfth of what it did: K32EnumProcesses every look, a name only for an id not seen before, the Toolhelp snapshot every thirty seconds as the net for a reused id. At start, one info line per hand-made entry Microsoft's own list (KnownGameList.bin, read for whole fields only) now covers, so the box can be unticked; status lists the games marked by hand. A first reading of the list wanted each folder name's length echoed after it and missed DS2; the rule is now two characters or more, with DS2's record as a byte-for-byte test. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The maintainer's run, 13:36-14:26: The Other Side detected from launch and from a tick mid-game, an untick mid-game leaving the session to end with the game, Starfield through the writer unchanged. The installed watcher at idle, nine minutes each against the published 0.2.0: 0.026 % of a core against 0.324 % -- twelve and a half times less, measured on the whole process. A first reading of 5.1 MB and 424 handles came after four sessions; `presence-probe footprint` runs the watcher's steps one by one and shows this lot's own cost is nil and no step leaks, while reading the GPU counters for the refinement, there since Lot 3, keeps 3.7 MB from the first session on. That and the handles gained over the first sessions are left for a separate piece of work. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A hand-made sighting carried its process id as an Option that a missing value would have turned into 0, a wait that ends at once; it is a field now. The game list's key, missing at start on a profile the Game Bar had not written yet, is tried again instead of never. Microsoft's list is decoded once into a List instead of twice per entry, names are compared in lower case beyond ASCII, and a record is read over three long folder names' worth instead of 600 bytes. The writer's path is lowercased once. Two rules sat inside system calls: which process is a sighting, and which hand-made entries Microsoft's list covers. Both are now pure functions -- sensor::sighting_among takes the path lookup as a parameter, hand_made::covered takes the decoded list -- with tests on made-up processes and records, a tracker test on a real child process born between two snapshots, and the relaunch scenario checks both waits. On a hosted runner sensor.rs goes from 8 % to 43 % of its lines, hand_made.rs from 37 % to 48 %; on a client machine the library is at 72.8 %. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
AGENTS.md gains two principles -- Microsoft's documentation before any spike, and a reader of real data is not done until it has read the real data; and the idle look as the program's only timer, measured on the whole installed process against the last release -- the rule that a check next to a system call is split from it and tested alone, and three pitfalls: script string literals eating backslashes, a packaged host's shell reading a stale private %APPDATA%, and the registry notification that never comes for the Game Bar's writes. The changelog gives the idle figures as measured, and the lot page records the review. Co-Authored-By: Claude Opus 5.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.
Windows never starts the Game Bar presence writer for a title the person marked with Remember this is a game, so the watcher never saw those games. It does now — from their launch, or from the moment the box is ticked mid-game — and the idle look that finds them costs a twelfth of what it did.
What changed for the person running it
Game detected: X, which is marked as a game by hand in the Game Bar), so a program ticked by mistake can be found and unticked.statuslists the games marked by hand, each with whether it runs and whether Microsoft knows it.How it was decided —
docs/design/15-marked-games.mdRevision 1, no XboxTitleId); the writer — Xbox presence — never starts for those.presence-probe watch-games,watch-methods) showed Windows writes the game's entry at every launch, and thatRegNotifyChangeKeyValuenever fires for the Game Bar's writes from an ordinary process, whichever of eight ways it is asked; WMI'sRegistryTreeChangeEventdoes. WMI was set aside by the maintainer until the reason is known; Microsoft's documentation namesRegRestoreKeyas the one blind spot, not confirmed.KnownGameList.bin(August, revision 2691, GUIDs matching the entries Windows creates from it); unticked, Windows recognised them. That is what the start hint is for.K32EnumProcesses, 32 µs), names only new ones (52 µs each), and keeps the Toolhelp snapshot (4 ms) every thirty seconds as the net for a reused id.How it is built
sensor::Sighting— the writer, or a hand-made game with its pid and exact signal; the engine parks on either's handle, does not refine a game marked by hand, and accepts either coming back within the grace. An untick mid-game takes effect at the next launch: noticing it would mean waking during the game.detect::hand_made(entries, and the list key's last-write time, re-read only when it moves),detect::process::Tracker(the cheap look),detect::microsoft_list(the undocumented file, read for whole fields only; a first version missed DS2 and was caught against the real file).sensor::sighting_among,hand_made::covered); three engine scenarios; a tracker test on a real child process. On a hosted runnersensor.rs43 %, the new modules 48–98 %; on a client machine the library is at 72.8 %.Verified in the field, 2026-09-23
The Other Side from launch and from a tick mid-game, an untick mid-game leaving the session to end with the game, Starfield through the writer unchanged, the idle cost against 0.2.0.
presence-probe footprintshows the lot's own memory and handles are nil; reading the GPU counters for the refinement (since Lot 3) keeps 3.7 MB after the first session — left for a separate piece of work.For the reviewer
AGENTS.mdgains Microsoft's documentation first, then measure and Cheap at rest, silent in game, the rule of splitting a check from its system call, and three pitfalls from this lot.presence-probegainswatch-games,watch-methods,cost,footprint,microsoft-list— instruments, not shipped behaviour.🤖 Generated with Claude Code