For a port that is a GitHub fork of its upstream, the upstream code it
carries is the merge base of the two, not upstream's HEAD. The bump moved
upstream_commit to upstream HEAD on snes9x, kronos, np2kai and others
whose pin was that base. The upstream view's head is now the merge base
GitHub's compare names, the way _follow_submodule already reads a
vendored submodule. Outside a fork network the HEAD stays.
check_version read latest_tag as the first entry of GitHub's REST
listing, which sorts by name (nesoid: 2.5 before 2.5-4, gargoyle:
stable-20090825 before 2026.1.1), and found the declared tag only on that
first page of 100. The newest tag now comes from GraphQL by commit date,
and the declared one is asked for by name on GitHub, GitLab and Forgejo.
The clean-tree guard of the write modes looked at the whole emulators
directory: a loop of --emulator X --rebase-refs refused every profile
after the first it wrote. It now looks at the selected profiles only.
A single 429 from git.libretro.com on cemu's tree ended profile_sync --all
with a traceback and no report for the other 646 profiles. upstream now
waits a 429 out (Retry-After up to 120 s, else 5, 20, 60 s), as
base_scraper already did, and stops asking a host that outlasts the
waits. profile_sync reports that profile as rate limited, fails the run,
and carries on with the other forges.
The -listxml names the software lists each machine and slot card
declares and the floppy drives it can instantiate. --devices now writes
one entry per hash/<list>.xml the release ships under the systems of its
placed machines (111 lists, 666 stay with hash/), and files each floppy
sample under the systems whose drives select its form factor
(floppy.cpp:1428-1473, 1759-1767).
Machines a registered platform declares under one of the profile's
systems seed the walk too: bbcb, cdimono1, cdimono2, dragon32, ep64 and
ep128. Unplaced device sets go from 903 to 861.
eduke32 and fury declare https://voidpoint.io/terminx/eduke32 and were
skipped as an unsupported host. The instance serves the GitLab v4 API
(/api/v4/projects/terminx%2Feduke32 answers 200) and /-/raw/ paths.
GitHub, GitLab and Gitea redirect a renamed repository, and every call
follows the redirect: AloysHF/NicaiEmu answers as AloysHF/CoolbarEmu
and the profile read as current. profile_sync now reads the name the
forge answers under and counts a move as review work.
Profiles, the wiki, comments, docstrings, command output and schema descriptions carried em-dashes, clause-joining semicolons, unicode arrows, box-drawing banners and check-mark glyphs. Each sentence was rewritten rather than having its character swapped. Hashes, paths, source_ref values and every cited file:line are unchanged, which a comparison of each parsed profile against the previous revision confirms.
validate_pr comments now say PASS and FAIL in words, and source_ref values in a profile's structured blocks render as code. test_prose_style fails if any of these comes back, in tracked files or in the generated site.
A tag looked up before it was pushed was cached as absent for good,
so a profile pinned on that release was never recognised as frozen
on it. The absence now expires; a tag found stays cached.
The commit list behind the triage drift score was cached for good,
so pushes upstream never moved a profile up the triage. It now
expires like the other moving answers.
Offline, fetch_file answered None for a path the cache never
stored, the same answer as a path known to be absent, and
profile_sync reported existing files as gone. A miss now raises
NotCachedError and the profile is reported unverified.
Four Switch profiles were unverifiable and said so on stderr every pass.
yuzu and suyu answer 451, citron's host stopped resolving, and
git.eden-emu.dev returns 403 to anything that is not a browser. Each
aborted its own report, so nothing could be said about any of them, and
the noise repeated on every run over the whole corpus.
A withdrawn forge is now a fact rather than a failure. GoneError covers
451, 410 and a host that does not resolve; none is retried, since three
attempts with backoff end in the same place. Those profiles land in
their own summary bucket, out of the review backlog where nobody could
act on them anyway. A 403 stays what it was, a refusal, because small
Forgejo instances behind anti-bot filters issue it routinely.
A profile can now name a source_mirror, consulted after source and
upstream so a live primary always decides attribution. Reaching it took
two more changes: a repository that refuses is muted for the rest of the
pass instead of ending it, keyed by host as well as slug because a
mirror carries the same slug on another forge; and a refused miss is not
cached, or the mute would answer for the mirror that was about to be
asked.
eden now reads from its Codeberg copy, which holds the same head and the
pinned commit: 5 refs, all anchored, where the profile could not be
checked at all. yuzu, suyu and citron have no mirror that serves
content, and now say so once instead of failing loudly.