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.
VPX moved file location into one class. FileLocator holds the read-only
application path and the preferences path, and picks between two layout
modes from where the application ini sits: AppPrefData splits static
data, settings and tables across three roots, AppOnly keeps everything
in the application folder. The profile still described m_szMyPath and
m_szMyPrefPath, identifiers the tree no longer carries.
Script lookup changed shape with it. SearchScript walks ten locations
case-insensitively, rooted on the table's own folder rather than the
working directory, where the profile documented seven. The editor's
completion parser left that search entirely: ParseVPCore opens core.vbs
at the Scripts subfolder alone and warns when it is absent.
The PinMAME root now prefers a pinmame folder beside the table before
the global setting and the platform default. vpx.html is served by the
web server, the LiveUI no longer naming it.
Four PinMAME citations read as external again: the project word is only
recognised behind a list delimiter, and one of them sat behind "at".
41 refs, 37 anchored, 4 external, none left to read.
MIN_BIOS_SIZE fell from 4 MB to 2 MB (BiosTools.cpp:16), which is what
admits the Namco System 246/256 COH-H chip dumps: those are 2 MB where a
console image is 4. The profile still declared the old floor, so it
described a gate the code had stopped applying.
Three changes travel with it. A COH-H board is region 11 rather than 8.
Its description is built from the EXTINFO serial, because Sony left the
version and date fields identical across those BIOSes, and the three
serials the code names resolve to System 256, System 246 Rack C and the
COH-H board. The ROM window is zero-filled before the read so its unused
upper half cannot retain the previous image.
The picker follows: .7d and .8g are accepted extensions, r27v1602f a
name hint. Both dumps are already in the collection, byte-identical to
the r27v1602f members of the MAME sys246 and sys256 sets, and the .7d is
the same content as 246C.bin, which Redump catalogues as Namco System
246 Rack C with the very serial the new code maps.
97 refs, all anchored, pin moved to the revision they describe.
The cited blocks moved by seven lines and their bodies changed only
where bfunction gave way to std::function: {&DSP1::read, &dsp1} is now
memfn(&DSP1::read, &dsp1). Which ROM is loaded, under what name, size
and hash, is untouched. Diff read before the recale.
LinApple 3.0.0 moved every ROM out of hand-written byte arrays into
res/roms/*.rom, which scripts/generate_roms.sh compiles into
EmbeddedRoms.cpp behind an ENABLE_ROM_* macro. The bytes survived the
move: every hash this profile recorded against the old string literals
matches the image that replaced it.
The macros are what matters. ENABLE_ROM_CLONE_BASE64A,
ENABLE_ROM_CLONE_PRAVETS and ENABLE_ROM_CLONE_TK3000E are OFF in the
default build, so Base64A, Pravets 82/8M/8C and TK-3000 //e refuse to
start: mem_initialize finds no rom_data, names the cmake flag and the
--rom option, and returns -1. Five system ROMs the user has to supply,
none of them documented until now. The collection already held them.
Also new: icon.bmp, which the SDL frontends read from disk through the
data search path, and the J-Plus system ROM the old profile did not
list. The tree behind the old refs is gone, so the notes describe the
one that replaced it: five frontends, src/core, src/apple2, and a
program_dir still declared and never assigned.
38 refs, all anchored. 9 of 9 files present.
A ref citing a bare filename, the way prose does, was matched against the
HEAD tree alone. A file that moved since the pin then resolved to its
HEAD path, which does not exist at the pin, and the ref reported GONE
with "pin revision missing": it failed for the one reason it never
should, its own success at HEAD.
The pin tree is searched first, HEAD stays the fallback, and the rename
search carries the pin path forward as it does for any written path.
This is what the resolver already documents for prefixed and suffixed
paths; the bare-name branch was the one that did not follow it.
linapple cites Memory.cpp, src/Memory.cpp at its pin and
src/apple2/Memory.cpp today. Its refs now name where the code went
instead of reporting it missing.
Upstream moved under 145 profiles: 679 refs shifted and 452 followed a
renamed file, against 6,483 that still anchor where they were written.
The recale rewrites the located ranges only, keeping the annotations and
the sentences that carry them, and 106 pins advance in the same commit
because refs and source_commit name one revision or the profile
describes two at once.
Nothing here was guessed. The 183 refs that are CHANGED, GONE or
AMBIGUOUS are untouched, and the 57 profiles holding them keep their old
pin until someone reads the diff: profile_sync refuses to recale a
profile while any of its refs needs a re-read. trident kept its pin too,
its annotated ref being one the writer will not rewrite.
--backfill-commits and --realign-prose have always printed what they
would write. --rebase-refs and --bump-commit took the flag and printed
nothing, so the only way to read a plan was to let it happen, and the
recale and the pin had to be done in two full network passes with
--force in between.
Both now plan. The plan runs the production write path over a throwaway
copy rather than a parallel branch, so it cannot drift from the write,
and the planned bump reads the text the recale would have left: a pin
held back by prose the same pass would move is no longer reported as
blocked. One pass does both, recale before bump on each profile.
bump_commit also stopped announcing a rewrite of the pin to the value it
already held. On the corpus that was 126 of 232 announcements, which
buried the 106 profiles that did move.
SHA256SUMS.txt sat beside the artifacts it vouches for, so whoever could
rewrite a release rewrote the list with it. The packs were already
reproducible, which answers corruption and lets a third party rebuild an
archive byte for byte; nothing answered a rewritten release.
The list is now signed with an ed25519 key kept for this alone, and the
public half is allowed_signers at the repository root, so verification
does not go through the release page: ssh-keygen -Y verify against the
committed file, then sha256sum --check. Rehearsed on all three outcomes:
a good signature, a tampered pack caught by the sums, a rewritten list
caught by the signature.
The release steps sign and upload the signature, the README points a
downloader at the procedure, and the reproducibility section says what
each half proves. Rotation keeps retired lines so past releases stay
verifiable. Three tests hold the trust root, the signing step and the
documented principal in agreement.
validate.yml triggered on pull_request alone, and it holds the only
unittest invocation in the repository: deploy-site.yml stops at
validate_schemas, generation and the freshness diff. Work lands on main
by direct push far more often than by pull request, so 1,318 cases were
guarding the road almost nothing takes.
The suite and the schema check now run on both events. validate-bios and
label-pr read pull request context and carry an event guard. The
concurrency group falls back to the ref, so a push series collapses to
the tip: what stays verified is the head of main.
The path lists are spelled out per event because the workflow parser
reads no YAML anchor, which PyYAML would have accepted in silence. Four
tests hold the wiring: the suite reachable from a push, the two path
lists equal, every job reading pull request context guarded, and no
anchor in any workflow.
The field reference carried the same attribution the FAQ did:
known_hash_adler32 described as Dolphin's IPL files, when dolphin.yml
declares it on dsp_rom.bin and dsp_coef.bin. The guard now scans every
wiki page rather than the FAQ alone.
The home page and the stats export counted every file carrying a
provenance record, the provenance page and the README only the system
files. The site published 553 and 566 for the same quantity, one click
apart, and the export paired the wider count with composition.systems as
its denominator. common.count_catalog_matched is now the single source,
scoped to the systems bucket.
The FAQ had drifted from the profiles it describes: MAME pinned at 0.287
against 0.289 in mame.yml, Adler-32 attributed to Dolphin's IPL rather
than the DSP ROMs that carry known_hash_adler32, and the per-emulator
verbose report named as the only content check on an existence platform,
which skips the DISCREPANCY line the platform report raises itself.
Tests read both sides: no generator may count matches inline, and each
FAQ claim is checked against the profile or the script that owns it.