apple / swift (pull_request) Successful in 1m27s
apple / screenshots (pull_request) Skipped
ci / rust-arm64 (pull_request) Successful in 1m22s
android / android (pull_request) Successful in 3m9s
ci / docs-site (pull_request) Successful in 1m9s
ci / web (pull_request) Successful in 3m20s
ci / rust (pull_request) Failing after 9m9s
The xbox scanner resolves each package's PackageFamilyName by enumerating %ProgramData%\Microsoft\Windows\AppRepository\Packages. Probed on .173 (design doc S1), that directory is: NT AUTHORITY\LocalService UnauthorizedAccessException <- the plugin runner LocalSystem count=348 <- the host service So an extracted xbox plugin cannot build an AUMID, and `aumid` — which takes a complete `<PFN>!<AppId>` — is unpublishable by one. The design doc offered two fallbacks: entries without `aumid` (they would list but not launch), or a one-shot elevated PFN resolve at install time. This is neither. The plugin sends `<Identity>!<AppId>`, both read straight out of MicrosoftGame.config — which IS readable de-privileged — and the host resolves the publisher hash at LAUNCH time, where it already owns command construction. That keeps D1 intact (the plugin supplies a validated value, the host builds the command), it is the same shape as the `playnite` kind, and resolving late means a package update that changes the publisher hash cannot leave a stale unlaunchable tile behind — which the install-time cache would have. `xbox_pfn` therefore moves from the scan path to the launch path rather than being deleted, and its doc records the privilege asymmetry so the next reader doesn't re-derive it. The charset guard is factored out (`aumid_part` / `valid_aumid`) and shared with the `aumid` kind. On `aumid` it was belt-and-braces — every value was host-derived. On `xbox` it is load-bearing: the Identity arrives over the wire from a plugin, and it is interpolated into a `shell:AppsFolder\…` argument. Validated inbound at reconcile too, so a malformed value is a 400 the plugin author can act on rather than a tile that fails on click. Gates: punktfunk-host 438 passed / 0 failed on .21, and 55/0 for the library tests on .173 (where these arms actually compile). Both counts +1 for the new guard test.